aboutsummaryrefslogtreecommitdiffstats
path: root/railties
diff options
context:
space:
mode:
Diffstat (limited to 'railties')
-rw-r--r--railties/CHANGELOG.md142
-rw-r--r--railties/RDOC_MAIN.rdoc104
-rw-r--r--railties/README.rdoc3
-rw-r--r--railties/Rakefile64
-rwxr-xr-xrailties/bin/test3
-rwxr-xr-xrailties/exe/rails1
-rw-r--r--railties/lib/minitest/rails_plugin.rb54
-rw-r--r--railties/lib/rails.rb2
-rw-r--r--railties/lib/rails/all.rb3
-rw-r--r--railties/lib/rails/api/generator.rb11
-rw-r--r--railties/lib/rails/api/task.rb12
-rw-r--r--railties/lib/rails/app_loader.rb23
-rw-r--r--railties/lib/rails/app_updater.rb34
-rw-r--r--railties/lib/rails/application.rb101
-rw-r--r--railties/lib/rails/application/bootstrap.rb2
-rw-r--r--railties/lib/rails/application/configuration.rb16
-rw-r--r--railties/lib/rails/application/default_middleware_stack.rb4
-rw-r--r--railties/lib/rails/application/finisher.rb2
-rw-r--r--railties/lib/rails/application/routes_reloader.rb2
-rw-r--r--railties/lib/rails/application_controller.rb2
-rw-r--r--railties/lib/rails/backtrace_cleaner.rb2
-rw-r--r--railties/lib/rails/cli.rb2
-rw-r--r--railties/lib/rails/code_statistics.rb2
-rw-r--r--railties/lib/rails/code_statistics_calculator.rb2
-rw-r--r--railties/lib/rails/command.rb2
-rw-r--r--railties/lib/rails/command/actions.rb8
-rw-r--r--railties/lib/rails/command/base.rb8
-rw-r--r--railties/lib/rails/command/behavior.rb2
-rw-r--r--railties/lib/rails/command/environment_argument.rb15
-rw-r--r--railties/lib/rails/command/helpers/editor.rb35
-rw-r--r--railties/lib/rails/commands.rb2
-rw-r--r--railties/lib/rails/commands/application/application_command.rb2
-rw-r--r--railties/lib/rails/commands/console/console_command.rb5
-rw-r--r--railties/lib/rails/commands/credentials/USAGE40
-rw-r--r--railties/lib/rails/commands/credentials/credentials_command.rb72
-rw-r--r--railties/lib/rails/commands/dbconsole/dbconsole_command.rb29
-rw-r--r--railties/lib/rails/commands/destroy/destroy_command.rb2
-rw-r--r--railties/lib/rails/commands/encrypted/encrypted_command.rb77
-rw-r--r--railties/lib/rails/commands/generate/generate_command.rb2
-rw-r--r--railties/lib/rails/commands/help/help_command.rb2
-rw-r--r--railties/lib/rails/commands/new/new_command.rb2
-rw-r--r--railties/lib/rails/commands/plugin/plugin_command.rb2
-rw-r--r--railties/lib/rails/commands/rake/rake_command.rb2
-rw-r--r--railties/lib/rails/commands/runner/USAGE3
-rw-r--r--railties/lib/rails/commands/runner/runner_command.rb10
-rw-r--r--railties/lib/rails/commands/secrets/secrets_command.rb27
-rw-r--r--railties/lib/rails/commands/server/server_command.rb35
-rw-r--r--railties/lib/rails/commands/test/test_command.rb27
-rw-r--r--railties/lib/rails/commands/version/version_command.rb2
-rw-r--r--railties/lib/rails/configuration.rb2
-rw-r--r--railties/lib/rails/console/app.rb2
-rw-r--r--railties/lib/rails/console/helpers.rb2
-rw-r--r--railties/lib/rails/dev_caching.rb3
-rw-r--r--railties/lib/rails/engine.rb2
-rw-r--r--railties/lib/rails/engine/commands.rb2
-rw-r--r--railties/lib/rails/engine/configuration.rb2
-rw-r--r--railties/lib/rails/engine/railties.rb2
-rw-r--r--railties/lib/rails/engine/updater.rb4
-rw-r--r--railties/lib/rails/gem_version.rb2
-rw-r--r--railties/lib/rails/generators.rb9
-rw-r--r--railties/lib/rails/generators/actions.rb77
-rw-r--r--railties/lib/rails/generators/actions/create_migration.rb2
-rw-r--r--railties/lib/rails/generators/active_model.rb2
-rw-r--r--railties/lib/rails/generators/app_base.rb146
-rw-r--r--railties/lib/rails/generators/base.rb39
-rw-r--r--railties/lib/rails/generators/css/assets/assets_generator.rb2
-rw-r--r--railties/lib/rails/generators/css/scaffold/scaffold_generator.rb8
-rw-r--r--railties/lib/rails/generators/erb.rb2
-rw-r--r--railties/lib/rails/generators/erb/controller/controller_generator.rb2
-rw-r--r--railties/lib/rails/generators/erb/controller/templates/view.html.erb.tt (renamed from railties/lib/rails/generators/erb/controller/templates/view.html.erb)0
-rw-r--r--railties/lib/rails/generators/erb/mailer/mailer_generator.rb2
-rw-r--r--railties/lib/rails/generators/erb/mailer/templates/view.html.erb.tt (renamed from railties/lib/rails/generators/erb/mailer/templates/view.html.erb)0
-rw-r--r--railties/lib/rails/generators/erb/mailer/templates/view.text.erb.tt (renamed from railties/lib/rails/generators/erb/mailer/templates/view.text.erb)0
-rw-r--r--railties/lib/rails/generators/erb/scaffold/scaffold_generator.rb2
-rw-r--r--railties/lib/rails/generators/erb/scaffold/templates/_form.html.erb.tt (renamed from railties/lib/rails/generators/erb/scaffold/templates/_form.html.erb)2
-rw-r--r--railties/lib/rails/generators/erb/scaffold/templates/edit.html.erb.tt (renamed from railties/lib/rails/generators/erb/scaffold/templates/edit.html.erb)0
-rw-r--r--railties/lib/rails/generators/erb/scaffold/templates/index.html.erb.tt (renamed from railties/lib/rails/generators/erb/scaffold/templates/index.html.erb)8
-rw-r--r--railties/lib/rails/generators/erb/scaffold/templates/new.html.erb.tt (renamed from railties/lib/rails/generators/erb/scaffold/templates/new.html.erb)0
-rw-r--r--railties/lib/rails/generators/erb/scaffold/templates/show.html.erb.tt (renamed from railties/lib/rails/generators/erb/scaffold/templates/show.html.erb)0
-rw-r--r--railties/lib/rails/generators/generated_attribute.rb4
-rw-r--r--railties/lib/rails/generators/js/assets/assets_generator.rb2
-rw-r--r--railties/lib/rails/generators/migration.rb2
-rw-r--r--railties/lib/rails/generators/model_helpers.rb2
-rw-r--r--railties/lib/rails/generators/named_base.rb76
-rw-r--r--railties/lib/rails/generators/rails/app/app_generator.rb63
-rw-r--r--railties/lib/rails/generators/rails/app/templates/Gemfile.tt (renamed from railties/lib/rails/generators/rails/app/templates/Gemfile)19
-rw-r--r--railties/lib/rails/generators/rails/app/templates/README.md.tt (renamed from railties/lib/rails/generators/rails/app/templates/README.md)0
-rw-r--r--railties/lib/rails/generators/rails/app/templates/Rakefile.tt (renamed from railties/lib/rails/generators/rails/app/templates/Rakefile)0
-rw-r--r--railties/lib/rails/generators/rails/app/templates/app/assets/javascripts/application.js.tt3
-rw-r--r--railties/lib/rails/generators/rails/app/templates/app/assets/javascripts/cable.js.tt (renamed from railties/lib/rails/generators/rails/app/templates/app/assets/javascripts/cable.js)0
-rw-r--r--railties/lib/rails/generators/rails/app/templates/app/assets/stylesheets/application.css.tt (renamed from railties/lib/rails/generators/rails/app/templates/app/assets/stylesheets/application.css)0
-rw-r--r--railties/lib/rails/generators/rails/app/templates/app/channels/application_cable/channel.rb.tt (renamed from railties/lib/rails/generators/rails/app/templates/app/channels/application_cable/channel.rb)0
-rw-r--r--railties/lib/rails/generators/rails/app/templates/app/channels/application_cable/connection.rb.tt (renamed from railties/lib/rails/generators/rails/app/templates/app/channels/application_cable/connection.rb)0
-rw-r--r--railties/lib/rails/generators/rails/app/templates/app/controllers/application_controller.rb.tt5
-rw-r--r--railties/lib/rails/generators/rails/app/templates/app/helpers/application_helper.rb.tt (renamed from railties/lib/rails/generators/rails/app/templates/app/helpers/application_helper.rb)0
-rw-r--r--railties/lib/rails/generators/rails/app/templates/app/jobs/application_job.rb.tt (renamed from railties/lib/rails/generators/rails/app/templates/app/jobs/application_job.rb)0
-rw-r--r--railties/lib/rails/generators/rails/app/templates/app/mailers/application_mailer.rb.tt (renamed from railties/lib/rails/generators/rails/app/templates/app/mailers/application_mailer.rb)0
-rw-r--r--railties/lib/rails/generators/rails/app/templates/app/models/application_record.rb.tt (renamed from railties/lib/rails/generators/rails/app/templates/app/models/application_record.rb)0
-rw-r--r--railties/lib/rails/generators/rails/app/templates/bin/bundle.tt (renamed from railties/lib/rails/generators/rails/app/templates/bin/bundle)0
-rw-r--r--railties/lib/rails/generators/rails/app/templates/bin/rails.tt (renamed from railties/lib/rails/generators/rails/app/templates/bin/rails)0
-rw-r--r--railties/lib/rails/generators/rails/app/templates/bin/rake.tt (renamed from railties/lib/rails/generators/rails/app/templates/bin/rake)0
-rw-r--r--railties/lib/rails/generators/rails/app/templates/bin/setup.tt7
-rw-r--r--railties/lib/rails/generators/rails/app/templates/bin/update.tt7
-rw-r--r--railties/lib/rails/generators/rails/app/templates/bin/yarn.tt (renamed from railties/lib/rails/generators/rails/app/templates/bin/yarn)6
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config.ru.tt (renamed from railties/lib/rails/generators/rails/app/templates/config.ru)0
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/application.rb.tt (renamed from railties/lib/rails/generators/rails/app/templates/config/application.rb)3
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/boot.rb.tt (renamed from railties/lib/rails/generators/rails/app/templates/config/boot.rb)1
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/cable.yml.tt (renamed from railties/lib/rails/generators/rails/app/templates/config/cable.yml)2
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/databases/frontbase.yml.tt (renamed from railties/lib/rails/generators/rails/app/templates/config/databases/frontbase.yml)0
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/databases/ibm_db.yml.tt (renamed from railties/lib/rails/generators/rails/app/templates/config/databases/ibm_db.yml)0
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/databases/jdbc.yml.tt (renamed from railties/lib/rails/generators/rails/app/templates/config/databases/jdbc.yml)0
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml.tt (renamed from railties/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml)2
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/databases/jdbcpostgresql.yml.tt (renamed from railties/lib/rails/generators/rails/app/templates/config/databases/jdbcpostgresql.yml)0
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/databases/jdbcsqlite3.yml.tt (renamed from railties/lib/rails/generators/rails/app/templates/config/databases/jdbcsqlite3.yml)0
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/databases/mysql.yml.tt (renamed from railties/lib/rails/generators/rails/app/templates/config/databases/mysql.yml)2
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/databases/oracle.yml.tt (renamed from railties/lib/rails/generators/rails/app/templates/config/databases/oracle.yml)0
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml.tt (renamed from railties/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml)0
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/databases/sqlite3.yml.tt (renamed from railties/lib/rails/generators/rails/app/templates/config/databases/sqlite3.yml)0
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/databases/sqlserver.yml.tt (renamed from railties/lib/rails/generators/rails/app/templates/config/databases/sqlserver.yml)4
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/environment.rb.tt (renamed from railties/lib/rails/generators/rails/app/templates/config/environment.rb)0
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt7
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt12
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt10
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/initializers/application_controller_renderer.rb6
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/initializers/application_controller_renderer.rb.tt8
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/initializers/backtrace_silencers.rb.tt (renamed from railties/lib/rails/generators/rails/app/templates/config/initializers/backtrace_silencers.rb)0
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/initializers/cookies_serializer.rb.tt (renamed from railties/lib/rails/generators/rails/app/templates/config/initializers/cookies_serializer.rb)0
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/initializers/cors.rb.tt (renamed from railties/lib/rails/generators/rails/app/templates/config/initializers/cors.rb)0
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/initializers/filter_parameter_logging.rb.tt (renamed from railties/lib/rails/generators/rails/app/templates/config/initializers/filter_parameter_logging.rb)0
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/initializers/inflections.rb.tt (renamed from railties/lib/rails/generators/rails/app/templates/config/initializers/inflections.rb)0
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/initializers/mime_types.rb.tt (renamed from railties/lib/rails/generators/rails/app/templates/config/initializers/mime_types.rb)0
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_5_2.rb.tt12
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/puma.rb.tt (renamed from railties/lib/rails/generators/rails/app/templates/config/puma.rb)0
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/routes.rb.tt (renamed from railties/lib/rails/generators/rails/app/templates/config/routes.rb)0
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/secrets.yml32
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/spring.rb.tt (renamed from railties/lib/rails/generators/rails/app/templates/config/spring.rb)4
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/storage.yml.tt35
-rw-r--r--railties/lib/rails/generators/rails/app/templates/gitignore.tt (renamed from railties/lib/rails/generators/rails/app/templates/gitignore)10
-rw-r--r--railties/lib/rails/generators/rails/app/templates/package.json.tt (renamed from railties/lib/rails/generators/rails/app/templates/package.json)0
-rw-r--r--railties/lib/rails/generators/rails/app/templates/ruby-version.tt1
-rw-r--r--railties/lib/rails/generators/rails/app/templates/test/application_system_test_case.rb.tt (renamed from railties/lib/rails/generators/rails/app/templates/test/application_system_test_case.rb)0
-rw-r--r--railties/lib/rails/generators/rails/app/templates/test/test_helper.rb.tt (renamed from railties/lib/rails/generators/rails/app/templates/test/test_helper.rb)2
-rw-r--r--railties/lib/rails/generators/rails/application_record/application_record_generator.rb9
-rw-r--r--railties/lib/rails/generators/rails/assets/assets_generator.rb2
-rw-r--r--railties/lib/rails/generators/rails/assets/templates/stylesheet.css2
-rw-r--r--railties/lib/rails/generators/rails/controller/controller_generator.rb20
-rw-r--r--railties/lib/rails/generators/rails/controller/templates/controller.rb.tt (renamed from railties/lib/rails/generators/rails/controller/templates/controller.rb)0
-rw-r--r--railties/lib/rails/generators/rails/credentials/credentials_generator.rb47
-rw-r--r--railties/lib/rails/generators/rails/encrypted_file/encrypted_file_generator.rb38
-rw-r--r--railties/lib/rails/generators/rails/encrypted_secrets/encrypted_secrets_generator.rb70
-rw-r--r--railties/lib/rails/generators/rails/encryption_key_file/encryption_key_file_generator.rb57
-rw-r--r--railties/lib/rails/generators/rails/generator/generator_generator.rb2
-rw-r--r--railties/lib/rails/generators/rails/helper/helper_generator.rb2
-rw-r--r--railties/lib/rails/generators/rails/helper/templates/helper.rb.tt (renamed from railties/lib/rails/generators/rails/helper/templates/helper.rb)0
-rw-r--r--railties/lib/rails/generators/rails/integration_test/integration_test_generator.rb2
-rw-r--r--railties/lib/rails/generators/rails/master_key/master_key_generator.rb51
-rw-r--r--railties/lib/rails/generators/rails/migration/migration_generator.rb2
-rw-r--r--railties/lib/rails/generators/rails/model/model_generator.rb2
-rw-r--r--railties/lib/rails/generators/rails/plugin/plugin_generator.rb27
-rw-r--r--railties/lib/rails/generators/rails/plugin/templates/%name%.gemspec.tt (renamed from railties/lib/rails/generators/rails/plugin/templates/%name%.gemspec)0
-rw-r--r--railties/lib/rails/generators/rails/plugin/templates/Gemfile.tt (renamed from railties/lib/rails/generators/rails/plugin/templates/Gemfile)1
-rw-r--r--railties/lib/rails/generators/rails/plugin/templates/MIT-LICENSE.tt (renamed from railties/lib/rails/generators/rails/plugin/templates/MIT-LICENSE)0
-rw-r--r--railties/lib/rails/generators/rails/plugin/templates/README.md.tt (renamed from railties/lib/rails/generators/rails/plugin/templates/README.md)2
-rw-r--r--railties/lib/rails/generators/rails/plugin/templates/Rakefile.tt (renamed from railties/lib/rails/generators/rails/plugin/templates/Rakefile)11
-rw-r--r--railties/lib/rails/generators/rails/plugin/templates/bin/rails.tt17
-rw-r--r--railties/lib/rails/generators/rails/plugin/templates/config/routes.rb.tt (renamed from railties/lib/rails/generators/rails/plugin/templates/config/routes.rb)0
-rw-r--r--railties/lib/rails/generators/rails/plugin/templates/gitignore9
-rw-r--r--railties/lib/rails/generators/rails/plugin/templates/gitignore.tt18
-rw-r--r--railties/lib/rails/generators/rails/plugin/templates/lib/%namespaced_name%.rb.tt (renamed from railties/lib/rails/generators/rails/plugin/templates/lib/%namespaced_name%.rb)4
-rw-r--r--railties/lib/rails/generators/rails/plugin/templates/lib/%namespaced_name%/engine.rb.tt (renamed from railties/lib/rails/generators/rails/plugin/templates/lib/%namespaced_name%/engine.rb)0
-rw-r--r--railties/lib/rails/generators/rails/plugin/templates/lib/%namespaced_name%/railtie.rb.tt5
-rw-r--r--railties/lib/rails/generators/rails/plugin/templates/lib/%namespaced_name%/version.rb.tt (renamed from railties/lib/rails/generators/rails/plugin/templates/lib/%namespaced_name%/version.rb)0
-rw-r--r--railties/lib/rails/generators/rails/plugin/templates/lib/tasks/%namespaced_name%_tasks.rake.tt (renamed from railties/lib/rails/generators/rails/plugin/templates/lib/tasks/%namespaced_name%_tasks.rake)0
-rw-r--r--railties/lib/rails/generators/rails/plugin/templates/rails/application.rb.tt (renamed from railties/lib/rails/generators/rails/plugin/templates/rails/application.rb)9
-rw-r--r--railties/lib/rails/generators/rails/plugin/templates/rails/boot.rb.tt (renamed from railties/lib/rails/generators/rails/plugin/templates/rails/boot.rb)0
-rw-r--r--railties/lib/rails/generators/rails/plugin/templates/rails/dummy_manifest.js.tt (renamed from railties/lib/rails/generators/rails/plugin/templates/rails/dummy_manifest.js)1
-rw-r--r--railties/lib/rails/generators/rails/plugin/templates/rails/engine_manifest.js.tt (renamed from railties/lib/rails/generators/rails/plugin/templates/rails/engine_manifest.js)0
-rw-r--r--railties/lib/rails/generators/rails/plugin/templates/rails/javascripts.js.tt (renamed from railties/lib/rails/generators/rails/plugin/templates/rails/javascripts.js)3
-rw-r--r--railties/lib/rails/generators/rails/plugin/templates/rails/routes.rb.tt (renamed from railties/lib/rails/generators/rails/plugin/templates/rails/routes.rb)0
-rw-r--r--railties/lib/rails/generators/rails/plugin/templates/test/%namespaced_name%_test.rb.tt (renamed from railties/lib/rails/generators/rails/plugin/templates/test/%namespaced_name%_test.rb)0
-rw-r--r--railties/lib/rails/generators/rails/plugin/templates/test/application_system_test_case.rb.tt (renamed from railties/lib/rails/generators/rails/plugin/templates/test/application_system_test_case.rb)0
-rw-r--r--railties/lib/rails/generators/rails/plugin/templates/test/integration/navigation_test.rb.tt (renamed from railties/lib/rails/generators/rails/plugin/templates/test/integration/navigation_test.rb)1
-rw-r--r--railties/lib/rails/generators/rails/plugin/templates/test/test_helper.rb.tt (renamed from railties/lib/rails/generators/rails/plugin/templates/test/test_helper.rb)5
-rw-r--r--railties/lib/rails/generators/rails/resource/USAGE2
-rw-r--r--railties/lib/rails/generators/rails/resource/resource_generator.rb2
-rw-r--r--railties/lib/rails/generators/rails/resource_route/resource_route_generator.rb45
-rw-r--r--railties/lib/rails/generators/rails/scaffold/scaffold_generator.rb5
-rw-r--r--railties/lib/rails/generators/rails/scaffold_controller/scaffold_controller_generator.rb2
-rw-r--r--railties/lib/rails/generators/rails/scaffold_controller/templates/api_controller.rb.tt (renamed from railties/lib/rails/generators/rails/scaffold_controller/templates/api_controller.rb)0
-rw-r--r--railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb.tt (renamed from railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb)4
-rw-r--r--railties/lib/rails/generators/rails/system_test/system_test_generator.rb2
-rw-r--r--railties/lib/rails/generators/rails/task/task_generator.rb2
-rw-r--r--railties/lib/rails/generators/rails/task/templates/task.rb.tt (renamed from railties/lib/rails/generators/rails/task/templates/task.rb)0
-rw-r--r--railties/lib/rails/generators/resource_helpers.rb2
-rw-r--r--railties/lib/rails/generators/test_case.rb2
-rw-r--r--railties/lib/rails/generators/test_unit.rb2
-rw-r--r--railties/lib/rails/generators/test_unit/controller/controller_generator.rb2
-rw-r--r--railties/lib/rails/generators/test_unit/controller/templates/functional_test.rb.tt (renamed from railties/lib/rails/generators/test_unit/controller/templates/functional_test.rb)0
-rw-r--r--railties/lib/rails/generators/test_unit/generator/generator_generator.rb2
-rw-r--r--railties/lib/rails/generators/test_unit/generator/templates/generator_test.rb.tt (renamed from railties/lib/rails/generators/test_unit/generator/templates/generator_test.rb)0
-rw-r--r--railties/lib/rails/generators/test_unit/helper/helper_generator.rb2
-rw-r--r--railties/lib/rails/generators/test_unit/integration/integration_generator.rb2
-rw-r--r--railties/lib/rails/generators/test_unit/integration/templates/integration_test.rb.tt (renamed from railties/lib/rails/generators/test_unit/integration/templates/integration_test.rb)0
-rw-r--r--railties/lib/rails/generators/test_unit/job/job_generator.rb4
-rw-r--r--railties/lib/rails/generators/test_unit/job/templates/unit_test.rb.tt (renamed from railties/lib/rails/generators/test_unit/job/templates/unit_test.rb.erb)0
-rw-r--r--railties/lib/rails/generators/test_unit/mailer/mailer_generator.rb2
-rw-r--r--railties/lib/rails/generators/test_unit/mailer/templates/functional_test.rb.tt (renamed from railties/lib/rails/generators/test_unit/mailer/templates/functional_test.rb)0
-rw-r--r--railties/lib/rails/generators/test_unit/mailer/templates/preview.rb.tt (renamed from railties/lib/rails/generators/test_unit/mailer/templates/preview.rb)0
-rw-r--r--railties/lib/rails/generators/test_unit/model/model_generator.rb2
-rw-r--r--railties/lib/rails/generators/test_unit/model/templates/fixtures.yml.tt (renamed from railties/lib/rails/generators/test_unit/model/templates/fixtures.yml)0
-rw-r--r--railties/lib/rails/generators/test_unit/model/templates/unit_test.rb.tt (renamed from railties/lib/rails/generators/test_unit/model/templates/unit_test.rb)0
-rw-r--r--railties/lib/rails/generators/test_unit/plugin/plugin_generator.rb2
-rw-r--r--railties/lib/rails/generators/test_unit/scaffold/scaffold_generator.rb21
-rw-r--r--railties/lib/rails/generators/test_unit/scaffold/templates/api_functional_test.rb.tt (renamed from railties/lib/rails/generators/test_unit/scaffold/templates/api_functional_test.rb)4
-rw-r--r--railties/lib/rails/generators/test_unit/scaffold/templates/functional_test.rb.tt (renamed from railties/lib/rails/generators/test_unit/scaffold/templates/functional_test.rb)4
-rw-r--r--railties/lib/rails/generators/test_unit/scaffold/templates/system_test.rb.tt49
-rw-r--r--railties/lib/rails/generators/test_unit/system/system_generator.rb2
-rw-r--r--railties/lib/rails/generators/test_unit/system/templates/application_system_test_case.rb.tt (renamed from railties/lib/rails/generators/test_unit/system/templates/application_system_test_case.rb)0
-rw-r--r--railties/lib/rails/generators/test_unit/system/templates/system_test.rb.tt (renamed from railties/lib/rails/generators/test_unit/system/templates/system_test.rb)0
-rw-r--r--railties/lib/rails/generators/testing/assertions.rb8
-rw-r--r--railties/lib/rails/generators/testing/behaviour.rb2
-rw-r--r--railties/lib/rails/generators/testing/setup_and_teardown.rb2
-rw-r--r--railties/lib/rails/info.rb4
-rw-r--r--railties/lib/rails/info_controller.rb2
-rw-r--r--railties/lib/rails/initializable.rb2
-rw-r--r--railties/lib/rails/mailers_controller.rb2
-rw-r--r--railties/lib/rails/paths.rb2
-rw-r--r--railties/lib/rails/plugin/test.rb10
-rw-r--r--railties/lib/rails/rack.rb2
-rw-r--r--railties/lib/rails/rack/logger.rb2
-rw-r--r--railties/lib/rails/railtie.rb5
-rw-r--r--railties/lib/rails/railtie/configurable.rb2
-rw-r--r--railties/lib/rails/railtie/configuration.rb2
-rw-r--r--railties/lib/rails/ruby_version_check.rb2
-rw-r--r--railties/lib/rails/secrets.rb28
-rw-r--r--railties/lib/rails/source_annotation_extractor.rb6
-rw-r--r--railties/lib/rails/tasks.rb2
-rw-r--r--railties/lib/rails/tasks/annotations.rake2
-rw-r--r--railties/lib/rails/tasks/dev.rake2
-rw-r--r--railties/lib/rails/tasks/engine.rake5
-rw-r--r--railties/lib/rails/tasks/framework.rake31
-rw-r--r--railties/lib/rails/tasks/initializers.rake2
-rw-r--r--railties/lib/rails/tasks/log.rake2
-rw-r--r--railties/lib/rails/tasks/middleware.rake2
-rw-r--r--railties/lib/rails/tasks/misc.rake2
-rw-r--r--railties/lib/rails/tasks/restart.rake3
-rw-r--r--railties/lib/rails/tasks/routes.rake2
-rw-r--r--railties/lib/rails/tasks/statistics.rake2
-rw-r--r--railties/lib/rails/tasks/tmp.rake13
-rw-r--r--railties/lib/rails/tasks/yarn.rake4
-rw-r--r--railties/lib/rails/test_help.rb3
-rw-r--r--railties/lib/rails/test_unit/line_filtering.rb73
-rw-r--r--railties/lib/rails/test_unit/minitest_plugin.rb145
-rw-r--r--railties/lib/rails/test_unit/railtie.rb2
-rw-r--r--railties/lib/rails/test_unit/reporter.rb9
-rw-r--r--railties/lib/rails/test_unit/runner.rb143
-rw-r--r--railties/lib/rails/test_unit/test_requirer.rb31
-rw-r--r--railties/lib/rails/test_unit/testing.rake18
-rw-r--r--railties/lib/rails/version.rb2
-rw-r--r--railties/lib/rails/welcome_controller.rb2
-rw-r--r--railties/railties.gemspec7
-rw-r--r--railties/test/abstract_unit.rb3
-rw-r--r--railties/test/app_loader_test.rb2
-rw-r--r--railties/test/application/asset_debugging_test.rb15
-rw-r--r--railties/test/application/assets_test.rb11
-rw-r--r--railties/test/application/bin_setup_test.rb4
-rw-r--r--railties/test/application/configuration/custom_test.rb2
-rw-r--r--railties/test/application/configuration_test.rb293
-rw-r--r--railties/test/application/console_test.rb33
-rw-r--r--railties/test/application/current_attributes_integration_test.rb4
-rw-r--r--railties/test/application/dbconsole_test.rb74
-rw-r--r--railties/test/application/generators_test.rb14
-rw-r--r--railties/test/application/help_test.rb6
-rw-r--r--railties/test/application/initializers/frameworks_test.rb16
-rw-r--r--railties/test/application/initializers/hooks_test.rb2
-rw-r--r--railties/test/application/initializers/i18n_test.rb4
-rw-r--r--railties/test/application/initializers/load_path_test.rb2
-rw-r--r--railties/test/application/initializers/notifications_test.rb2
-rw-r--r--railties/test/application/integration_test_case_test.rb17
-rw-r--r--railties/test/application/loading_test.rb12
-rw-r--r--railties/test/application/mailer_previews_test.rb6
-rw-r--r--railties/test/application/middleware/cache_test.rb12
-rw-r--r--railties/test/application/middleware/cookies_test.rb147
-rw-r--r--railties/test/application/middleware/exceptions_test.rb4
-rw-r--r--railties/test/application/middleware/remote_ip_test.rb2
-rw-r--r--railties/test/application/middleware/sendfile_test.rb6
-rw-r--r--railties/test/application/middleware/session_test.rb70
-rw-r--r--railties/test/application/middleware/static_test.rb2
-rw-r--r--railties/test/application/middleware_test.rb4
-rw-r--r--railties/test/application/multiple_applications_test.rb2
-rw-r--r--railties/test/application/paths_test.rb2
-rw-r--r--railties/test/application/per_request_digest_cache_test.rb2
-rw-r--r--railties/test/application/rack/logger_test.rb2
-rw-r--r--railties/test/application/rackup_test.rb2
-rw-r--r--railties/test/application/rake/dbs_test.rb229
-rw-r--r--railties/test/application/rake/dev_test.rb22
-rw-r--r--railties/test/application/rake/framework_test.rb2
-rw-r--r--railties/test/application/rake/log_test.rb4
-rw-r--r--railties/test/application/rake/migrations_test.rb447
-rw-r--r--railties/test/application/rake/notes_test.rb5
-rw-r--r--railties/test/application/rake/restart_test.rb17
-rw-r--r--railties/test/application/rake/tmp_test.rb43
-rw-r--r--railties/test/application/rake_test.rb186
-rw-r--r--railties/test/application/rendering_test.rb2
-rw-r--r--railties/test/application/routing_test.rb8
-rw-r--r--railties/test/application/runner_test.rb53
-rw-r--r--railties/test/application/server_test.rb61
-rw-r--r--railties/test/application/test_runner_test.rb88
-rw-r--r--railties/test/application/test_test.rb20
-rw-r--r--railties/test/application/url_generation_test.rb3
-rw-r--r--railties/test/application/version_test.rb6
-rw-r--r--railties/test/backtrace_cleaner_test.rb2
-rw-r--r--railties/test/code_statistics_calculator_test.rb2
-rw-r--r--railties/test/code_statistics_test.rb2
-rw-r--r--railties/test/command/base_test.rb4
-rw-r--r--railties/test/commands/console_test.rb50
-rw-r--r--railties/test/commands/credentials_test.rb52
-rw-r--r--railties/test/commands/dbconsole_test.rb67
-rw-r--r--railties/test/commands/encrypted_test.rb80
-rw-r--r--railties/test/commands/secrets_test.rb63
-rw-r--r--railties/test/commands/server_test.rb28
-rw-r--r--railties/test/configuration/middleware_stack_proxy_test.rb2
-rw-r--r--railties/test/console_helpers.rb25
-rw-r--r--railties/test/engine/commands_test.rb26
-rw-r--r--railties/test/engine/test_test.rb31
-rw-r--r--railties/test/engine_test.rb2
-rw-r--r--railties/test/env_helpers.rb2
-rw-r--r--railties/test/fixtures/about_yml_plugins/bad_about_yml/about.yml1
-rw-r--r--railties/test/fixtures/about_yml_plugins/bad_about_yml/init.rb1
-rw-r--r--railties/test/fixtures/about_yml_plugins/plugin_without_about_yml/init.rb1
-rw-r--r--railties/test/fixtures/lib/create_test_dummy_template.rb2
-rw-r--r--railties/test/fixtures/lib/generators/active_record/fixjour_generator.rb2
-rw-r--r--railties/test/fixtures/lib/generators/fixjour_generator.rb2
-rw-r--r--railties/test/fixtures/lib/generators/model_generator.rb2
-rw-r--r--railties/test/fixtures/lib/generators/usage_template/usage_template_generator.rb2
-rw-r--r--railties/test/fixtures/lib/rails/generators/foobar/foobar_generator.rb2
-rw-r--r--railties/test/fixtures/lib/template.rb2
-rw-r--r--railties/test/generators/actions_test.rb112
-rw-r--r--railties/test/generators/api_app_generator_test.rb61
-rw-r--r--railties/test/generators/app_generator_test.rb336
-rw-r--r--railties/test/generators/application_record_generator_test.rb16
-rw-r--r--railties/test/generators/argv_scrubber_test.rb5
-rw-r--r--railties/test/generators/assets_generator_test.rb2
-rw-r--r--railties/test/generators/channel_generator_test.rb2
-rw-r--r--railties/test/generators/controller_generator_test.rb9
-rw-r--r--railties/test/generators/create_migration_test.rb10
-rw-r--r--railties/test/generators/encrypted_secrets_generator_test.rb42
-rw-r--r--railties/test/generators/generated_attribute_test.rb2
-rw-r--r--railties/test/generators/generator_generator_test.rb2
-rw-r--r--railties/test/generators/generator_test.rb2
-rw-r--r--railties/test/generators/generators_test_helper.rb6
-rw-r--r--railties/test/generators/helper_generator_test.rb2
-rw-r--r--railties/test/generators/integration_test_generator_test.rb2
-rw-r--r--railties/test/generators/job_generator_test.rb2
-rw-r--r--railties/test/generators/mailer_generator_test.rb2
-rw-r--r--railties/test/generators/migration_generator_test.rb24
-rw-r--r--railties/test/generators/model_generator_test.rb21
-rw-r--r--railties/test/generators/named_base_test.rb41
-rw-r--r--railties/test/generators/namespaced_generators_test.rb15
-rw-r--r--railties/test/generators/orm_test.rb2
-rw-r--r--railties/test/generators/plugin_generator_test.rb146
-rw-r--r--railties/test/generators/plugin_test_helper.rb2
-rw-r--r--railties/test/generators/plugin_test_runner_test.rb10
-rw-r--r--railties/test/generators/resource_generator_test.rb2
-rw-r--r--railties/test/generators/scaffold_controller_generator_test.rb27
-rw-r--r--railties/test/generators/scaffold_generator_test.rb45
-rw-r--r--railties/test/generators/shared_generator_tests.rb251
-rw-r--r--railties/test/generators/system_test_generator_test.rb2
-rw-r--r--railties/test/generators/task_generator_test.rb2
-rw-r--r--railties/test/generators/test_runner_in_engine_test.rb2
-rw-r--r--railties/test/generators_test.rb19
-rw-r--r--railties/test/initializable_test.rb2
-rw-r--r--railties/test/isolation/abstract_unit.rb127
-rw-r--r--railties/test/json_params_parsing_test.rb2
-rw-r--r--railties/test/path_generation_test.rb6
-rw-r--r--railties/test/paths_test.rb2
-rw-r--r--railties/test/rack_logger_test.rb2
-rw-r--r--railties/test/rails_info_controller_test.rb2
-rw-r--r--railties/test/rails_info_test.rb15
-rw-r--r--railties/test/railties/engine_test.rb192
-rw-r--r--railties/test/railties/generators_test.rb2
-rw-r--r--railties/test/railties/mounted_engine_test.rb23
-rw-r--r--railties/test/railties/railtie_test.rb2
-rw-r--r--railties/test/secrets_test.rb102
-rw-r--r--railties/test/test_unit/reporter_test.rb11
-rw-r--r--railties/test/version_test.rb2
386 files changed, 5122 insertions, 1886 deletions
diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md
index d93c532c7e..d086248278 100644
--- a/railties/CHANGELOG.md
+++ b/railties/CHANGELOG.md
@@ -1,10 +1,150 @@
+* Deprecate `after_bundle` callback in Rails plugin templates.
+
+ *Yuji Yaginuma*
+
+* `rails new` and `rails plugin new` get `Active Storage` by default.
+ Add ability to skip `Active Storage` with `--skip-active-storage`
+ and do so automatically when `--skip-active-record` is used.
+
+ *bogdanvlviv*
+
+* Gemfile for new apps: upgrade redis-rb from ~> 3.0 to 4.0.
+
+ *Jeremy Daer*
+
+* Add `mini_magick` to default `Gemfile` as comment.
+
+ *Yoshiyuki Hirano*
+
+* Derive `secret_key_base` from the app name in development and test environments.
+
+ Spares away needless secret configs.
+
+ *DHH*, *Kasper Timm Hansen*
+
+* Support multiple versions arguments for `gem` method of Generators.
+
+ *Yoshiyuki Hirano*
+
+* Add `--skip-yarn` option to the plugin generator.
+
+ *bogdanvlviv*
+
+* Optimize routes indentation.
+
+ *Yoshiyuki Hirano*
+
+* Optimize indentation for generator actions.
+
+ *Yoshiyuki Hirano*
+
+* Skip unused components when running `bin/rails` in Rails plugin.
+
+ *Yoshiyuki Hirano*
+
+* Add `git_source` to `Gemfile` for plugin generator.
+
+ *Yoshiyuki Hirano*
+
+* Add `--skip-action-cable` option to the plugin generator.
+
+ *bogdanvlviv*
+
+* Deprecate support of use `Rails::Application` subclass to start Rails server.
+
+ *Yuji Yaginuma*
+
+* Add `ruby x.x.x` version to `Gemfile` and create `.ruby-version`
+ root file containing the current Ruby version when new Rails applications are
+ created.
+
+ *Alberto Almagro*
+
+* Support `-` as a platform-agnostic way to run a script from stdin with
+ `rails runner`
+
+ *Cody Cutrer*
+
+* Add `bootsnap` to default `Gemfile`.
+
+ *Burke Libbey*
+
+* Properly expand shortcuts for environment's name running the `console`
+ and `dbconsole` commands.
+
+ *Robin Dupret*
+
+* Passing the environment's name as a regular argument to the
+ `rails dbconsole` and `rails console` commands is deprecated.
+ The `-e` option should be used instead.
+
+ Previously:
+
+ $ bin/rails dbconsole production
+
+ Now:
+
+ $ bin/rails dbconsole -e production
+
+ *Robin Dupret*, *Kasper Timm Hansen*
+
+* Allow passing a custom connection name to the `rails dbconsole`
+ command when using a 3-level database configuration.
+
+ $ bin/rails dbconsole -c replica
+
+ *Robin Dupret*, *Jeremy Daer*
+
+* Skip unused components when running `bin/rails app:update`.
+
+ If the initial app generation skipped Action Cable, Active Record etc.,
+ the update task honors those skips too.
+
+ *Yuji Yaginuma*
+
+* Make Rails' test runner work better with minitest plugins.
+
+ By demoting the Rails test runner to just another minitest plugin —
+ and thereby not eager loading it — we can co-exist much better with
+ other minitest plugins such as pride and minitest-focus.
+
+ *Kasper Timm Hansen*
+
+* Load environment file in `dbconsole` command.
+
+ Fixes #29717.
+
+ *Yuji Yaginuma*
+
+* Add `rails secrets:show` command.
+
+ *Yuji Yaginuma*
+
+* Allow mounting the same engine several times in different locations.
+
+ Fixes #20204.
+
+ *David Rodríguez*
+
+* Clear screenshot files in `tmp:clear` task.
+
+ *Yuji Yaginuma*
+
+* Add `railtie.rb` to the plugin generator
+
+ *Tsukuru Tanimichi*
+
+* Deprecate `capify!` method in generators and templates.
+
+ *Yuji Yaginuma*
+
* Allow irb options to be passed from `rails console` command.
Fixes #28988.
*Yuji Yaginuma*
-* Added a shared section to config/database.yml that will be loaded for all environments.
+* Added a shared section to `config/database.yml` that will be loaded for all environments.
*Pierre Schambacher*
diff --git a/railties/RDOC_MAIN.rdoc b/railties/RDOC_MAIN.rdoc
index 654c7bae57..c70a9f0ba0 100644
--- a/railties/RDOC_MAIN.rdoc
+++ b/railties/RDOC_MAIN.rdoc
@@ -1,35 +1,50 @@
== Welcome to \Rails
-\Rails is a web-application framework that includes everything needed to create
-database-backed web applications according to the {Model-View-Controller (MVC)}[http://en.wikipedia.org/wiki/Model-view-controller] pattern.
-
-Understanding the MVC pattern is key to understanding \Rails. MVC divides your application
-into three layers, each with a specific responsibility.
-
-The View layer is composed of "templates" that are responsible for providing
-appropriate representations of your application's resources. Templates
-can come in a variety of formats, but most view templates are \HTML with embedded Ruby
-code (.erb files).
-
-The Model layer represents your domain model (such as Account, Product, Person, Post)
-and encapsulates the business logic that is specific to your application. In \Rails,
-database-backed model classes are derived from ActiveRecord::Base. Active Record allows
-you to present the data from database rows as objects and embellish these data objects
-with business logic methods. Although most \Rails models are backed by a database, models
-can also be ordinary Ruby classes, or Ruby classes that implement a set of interfaces as
-provided by the ActiveModel module. You can read more about Active Record in its
-{README}[link:files/activerecord/README_rdoc.html].
-
-The Controller layer is responsible for handling incoming HTTP requests and providing a
-suitable response. Usually this means returning \HTML, but \Rails controllers can also
-generate XML, JSON, PDFs, mobile-specific views, and more. Controllers manipulate models
-and render view templates in order to generate the appropriate HTTP response.
-
-In \Rails, the Controller and View layers are handled together by Action Pack.
-These two layers are bundled in a single package due to their heavy interdependence.
-This is unlike the relationship between Active Record and Action Pack, which are
-independent. Each of these packages can be used independently outside of \Rails. You
-can read more about Action Pack in its {README}[link:files/actionpack/README_rdoc.html].
+\Rails is a web-application framework that includes everything needed to
+create database-backed web applications according to the
+{Model-View-Controller (MVC)}[http://en.wikipedia.org/wiki/Model-view-controller]
+pattern.
+
+Understanding the MVC pattern is key to understanding \Rails. MVC divides your
+application into three layers, each with a specific responsibility.
+
+The <em>Model layer</em> represents your domain model (such as Account, Product,
+Person, Post, etc.) and encapsulates the business logic that is specific to
+your application. In \Rails, database-backed model classes are derived from
+ActiveRecord::Base. Active Record allows you to present the data from
+database rows as objects and embellish these data objects with business logic
+methods. You can read more about Active Record in its {README}[link:files/activerecord/README_rdoc.html].
+Although most \Rails models are backed by a database, models can also be ordinary
+Ruby classes, or Ruby classes that implement a set of interfaces as provided by
+the Active Model module. You can read more about Active Model in its {README}[link:files/activemodel/README_rdoc.html].
+
+The <em>Controller layer</em> is responsible for handling incoming HTTP requests and
+providing a suitable response. Usually this means returning \HTML, but \Rails controllers
+can also generate XML, JSON, PDFs, mobile-specific views, and more. Controllers load and
+manipulate models, and render view templates in order to generate the appropriate HTTP response.
+In \Rails, incoming requests are routed by Action Dispatch to an appropriate controller, and
+controller classes are derived from ActionController::Base. Action Dispatch and Action Controller
+are bundled together in Action Pack. You can read more about Action Pack in its
+{README}[link:files/actionpack/README_rdoc.html].
+
+The <em>View layer</em> is composed of "templates" that are responsible for providing
+appropriate representations of your application's resources. Templates can
+come in a variety of formats, but most view templates are \HTML with embedded
+Ruby code (ERB files). Views are typically rendered to generate a controller response,
+or to generate the body of an email. In \Rails, View generation is handled by Action View.
+You can read more about Action View in its {README}[link:files/actionview/README_rdoc.html].
+
+Active Record, Active Model, Action Pack, and Action View can each be used independently outside \Rails.
+In addition to that, \Rails also comes with Action Mailer ({README}[link:files/actionmailer/README_rdoc.html]), a library
+to generate and send emails; Active Job ({README}[link:files/activejob/README_md.html]), a
+framework for declaring jobs and making them run on a variety of queueing
+backends; Action Cable ({README}[link:files/actioncable/README_md.html]), a framework to
+integrate WebSockets with a \Rails application;
+Active Storage ({README}[link:files/activestorage/README_md.html]), a library to attach cloud
+and local files to \Rails applications;
+and Active Support ({README}[link:files/activesupport/README_rdoc.html]), a collection
+of utility classes and standard library extensions that are useful for \Rails,
+and may also be used independently outside \Rails.
== Getting Started
@@ -45,29 +60,32 @@ can read more about Action Pack in its {README}[link:files/actionpack/README_rdo
3. Change directory to +myapp+ and start the web server:
- $ cd myapp; rails server
+ $ cd myapp
+ $ rails server
Run with <tt>--help</tt> or <tt>-h</tt> for options.
-4. Go to http://localhost:3000 and you'll see:
-
- "Yay! You’re on Rails!"
+4. Go to <tt>http://localhost:3000</tt> and you'll see: "Yay! You’re on \Rails!"
5. Follow the guidelines to start developing your application. You may find the following resources handy:
-* The \README file created within your application.
-* {Getting Started with \Rails}[http://guides.rubyonrails.org/getting_started.html].
-* {Ruby on \Rails Tutorial}[https://www.railstutorial.org/book].
-* {Ruby on \Rails Guides}[http://guides.rubyonrails.org].
-* {The API Documentation}[http://api.rubyonrails.org].
+ * The \README file created within your application.
+ * {Getting Started with \Rails}[http://guides.rubyonrails.org/getting_started.html].
+ * {Ruby on \Rails Guides}[http://guides.rubyonrails.org].
+ * {The API Documentation}[http://api.rubyonrails.org].
+ * {Ruby on \Rails Tutorial}[https://www.railstutorial.org/book].
== Contributing
-We encourage you to contribute to Ruby on \Rails! Please check out the {Contributing to Rails
-guide}[http://edgeguides.rubyonrails.org/contributing_to_ruby_on_rails.html] for guidelines about how
-to proceed. {Join us}[http://contributors.rubyonrails.org]!
+We encourage you to contribute to Ruby on \Rails! Please check out the
+{Contributing to Ruby on \Rails guide}[http://guides.rubyonrails.org/contributing_to_ruby_on_rails.html] for guidelines about how to proceed. {Join us!}[http://contributors.rubyonrails.org]
+
+Trying to report a possible security vulnerability in \Rails? Please
+check out our {security policy}[http://rubyonrails.org/security/] for
+guidelines about how to proceed.
+Everyone interacting in \Rails and its sub-projects' codebases, issue trackers, chat rooms, and mailing lists is expected to follow the \Rails {code of conduct}[http://rubyonrails.org/conduct/].
== License
-Ruby on \Rails is released under the {MIT License}[http://www.opensource.org/licenses/MIT].
+Ruby on \Rails is released under the {MIT License}[https://opensource.org/licenses/MIT].
diff --git a/railties/README.rdoc b/railties/README.rdoc
index a25658668c..2715ccac3f 100644
--- a/railties/README.rdoc
+++ b/railties/README.rdoc
@@ -23,7 +23,7 @@ Source code can be downloaded as part of the Rails project on GitHub
Railties is released under the MIT license:
-* http://www.opensource.org/licenses/MIT
+* https://opensource.org/licenses/MIT
== Support
@@ -38,4 +38,3 @@ Bug reports can be filed for the Ruby on Rails project here:
Feature requests should be discussed on the rails-core mailing list here:
* https://groups.google.com/forum/?fromgroups#!forum/rubyonrails-core
-
diff --git a/railties/Rakefile b/railties/Rakefile
index d6284b7dc5..74615d2358 100644
--- a/railties/Rakefile
+++ b/railties/Rakefile
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rake/testtask"
task default: :test
@@ -9,19 +11,61 @@ task test: "test:isolated"
namespace :test do
task :isolated do
+ dash_i = [
+ "test",
+ "lib",
+ "../activesupport/lib",
+ "../actionpack/lib",
+ "../actionview/lib",
+ "../activemodel/lib"
+ ].map { |dir| File.expand_path(dir, __dir__) }
+
+ dash_i.reverse_each do |x|
+ $:.unshift(x) unless $:.include?(x)
+ end
+ $-w = true
+
+ require "bundler/setup" unless defined?(Bundler)
+ require "active_support"
+
+ failing_files = []
+
dirs = (ENV["TEST_DIR"] || ENV["TEST_DIRS"] || "**").split(",")
test_files = dirs.map { |dir| "test/#{dir}/*_test.rb" }
Dir[*test_files].each do |file|
- next true if file.include?("fixtures")
- dash_i = [
- "test",
- "lib",
- "#{__dir__}/../activesupport/lib",
- "#{__dir__}/../actionpack/lib",
- "#{__dir__}/../actionview/lib",
- "#{__dir__}/../activemodel/lib"
- ]
- ruby "-w", "-I#{dash_i.join ':'}", file
+ next true if file.start_with?("test/fixtures/")
+
+ fake_command = Shellwords.join([
+ FileUtils::RUBY,
+ "-w",
+ *dash_i.map { |dir| "-I#{Pathname.new(dir).relative_path_from(Pathname.pwd)}" },
+ file,
+ ])
+ puts fake_command
+
+ # We could run these in parallel, but pretty much all of the
+ # railties tests already run in parallel, so ¯\_(⊙︿⊙)_/¯
+ Process.waitpid fork {
+ ARGV.clear
+ Rake.application = nil
+
+ load file
+ }
+
+ unless $?.success?
+ failing_files << file
+ end
+ end
+
+ unless failing_files.empty?
+ puts
+ puts "Failed in:"
+ failing_files.each do |file|
+ puts " #{file}"
+ end
+ puts
+
+ raise "Failure in isolated test runner"
end
end
end
diff --git a/railties/bin/test b/railties/bin/test
index a7beb14b27..c53377cc97 100755
--- a/railties/bin/test
+++ b/railties/bin/test
@@ -1,4 +1,5 @@
#!/usr/bin/env ruby
+# frozen_string_literal: true
COMPONENT_ROOT = File.expand_path("..", __dir__)
-require File.expand_path("../tools/test", COMPONENT_ROOT)
+require_relative "../../tools/test"
diff --git a/railties/exe/rails b/railties/exe/rails
index a5635c2297..79af4db6b6 100755
--- a/railties/exe/rails
+++ b/railties/exe/rails
@@ -1,4 +1,5 @@
#!/usr/bin/env ruby
+# frozen_string_literal: true
git_path = File.expand_path("../../.git", __dir__)
diff --git a/railties/lib/minitest/rails_plugin.rb b/railties/lib/minitest/rails_plugin.rb
new file mode 100644
index 0000000000..6901b0bbc8
--- /dev/null
+++ b/railties/lib/minitest/rails_plugin.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+
+require "active_support/core_ext/module/attribute_accessors"
+require "rails/test_unit/reporter"
+require "rails/test_unit/runner"
+
+module Minitest
+ class SuppressedSummaryReporter < SummaryReporter
+ # Disable extra failure output after a run if output is inline.
+ def aggregated_results(*)
+ super unless options[:output_inline]
+ end
+ end
+
+ def self.plugin_rails_options(opts, options)
+ Rails::TestUnit::Runner.attach_before_load_options(opts)
+
+ opts.on("-b", "--backtrace", "Show the complete backtrace") do
+ options[:full_backtrace] = true
+ end
+
+ opts.on("-d", "--defer-output", "Output test failures and errors after the test run") do
+ options[:output_inline] = false
+ end
+
+ opts.on("-f", "--fail-fast", "Abort test run on first failure or error") do
+ options[:fail_fast] = true
+ end
+
+ opts.on("-c", "--[no-]color", "Enable color in the output") do |value|
+ options[:color] = value
+ end
+
+ options[:color] = true
+ options[:output_inline] = true
+ end
+
+ # Owes great inspiration to test runner trailblazers like RSpec,
+ # minitest-reporters, maxitest and others.
+ def self.plugin_rails_init(options)
+ unless options[:full_backtrace] || ENV["BACKTRACE"]
+ # Plugin can run without Rails loaded, check before filtering.
+ Minitest.backtrace_filter = ::Rails.backtrace_cleaner if ::Rails.respond_to?(:backtrace_cleaner)
+ end
+
+ # Replace progress reporter for colors.
+ reporter.reporters.delete_if { |reporter| reporter.kind_of?(SummaryReporter) || reporter.kind_of?(ProgressReporter) }
+ reporter << SuppressedSummaryReporter.new(options[:io], options)
+ reporter << ::Rails::TestUnitReporter.new(options[:io], options)
+ end
+
+ # Backwardscompatibility with Rails 5.0 generated plugin test scripts
+ mattr_reader :run_via, default: {}
+end
diff --git a/railties/lib/rails.rb b/railties/lib/rails.rb
index 6d8bf28943..092105d502 100644
--- a/railties/lib/rails.rb
+++ b/railties/lib/rails.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rails/ruby_version_check"
require "pathname"
diff --git a/railties/lib/rails/all.rb b/railties/lib/rails/all.rb
index 7606ea0e46..f5dccd2381 100644
--- a/railties/lib/rails/all.rb
+++ b/railties/lib/rails/all.rb
@@ -1,7 +1,10 @@
+# frozen_string_literal: true
+
require "rails"
%w(
active_record/railtie
+ active_storage/engine
action_controller/railtie
action_view/railtie
action_mailer/railtie
diff --git a/railties/lib/rails/api/generator.rb b/railties/lib/rails/api/generator.rb
index dcc491783c..3405560b74 100644
--- a/railties/lib/rails/api/generator.rb
+++ b/railties/lib/rails/api/generator.rb
@@ -1,11 +1,16 @@
+# frozen_string_literal: true
+
require "sdoc"
class RDoc::Generator::API < RDoc::Generator::SDoc # :nodoc:
RDoc::RDoc.add_generator self
def generate_class_tree_level(classes, visited = {})
- # Only process core extensions on the first visit.
+ # Only process core extensions on the first visit and remove
+ # Active Storage duplicated classes that are at the top level
+ # since they aren't nested under a definition of the `ActiveStorage` module.
if visited.empty?
+ classes = classes.reject { |klass| active_storage?(klass) }
core_exts, classes = classes.partition { |klass| core_extension?(klass) }
super.unshift([ "Core extensions", "", "", build_core_ext_subtree(core_exts, visited) ])
@@ -25,4 +30,8 @@ class RDoc::Generator::API < RDoc::Generator::SDoc # :nodoc:
def core_extension?(klass)
klass.name != "ActiveSupport" && klass.in_files.any? { |file| file.absolute_name.include?("core_ext") }
end
+
+ def active_storage?(klass)
+ klass.name != "ActiveStorage" && klass.in_files.all? { |file| file.absolute_name.include?("active_storage") }
+ end
end
diff --git a/railties/lib/rails/api/task.rb b/railties/lib/rails/api/task.rb
index 49267c2329..e7f0557584 100644
--- a/railties/lib/rails/api/task.rb
+++ b/railties/lib/rails/api/task.rb
@@ -1,5 +1,7 @@
+# frozen_string_literal: true
+
require "rdoc/task"
-require_relative "generator"
+require "rails/api/generator"
module Rails
module API
@@ -64,6 +66,14 @@ module Rails
)
},
+ "activestorage" => {
+ include: %w(
+ README.md
+ app/**/active_storage/**/*.rb
+ lib/active_storage/**/*.rb
+ )
+ },
+
"railties" => {
include: %w(
README.rdoc
diff --git a/railties/lib/rails/app_loader.rb b/railties/lib/rails/app_loader.rb
index 525d5f0161..20eb75d95c 100644
--- a/railties/lib/rails/app_loader.rb
+++ b/railties/lib/rails/app_loader.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "pathname"
require "rails/version"
@@ -8,15 +10,26 @@ module Rails
RUBY = Gem.ruby
EXECUTABLES = ["bin/rails", "script/rails"]
BUNDLER_WARNING = <<EOS
-Looks like your app's ./bin/rails is a stub that was generated by Bundler.
+Beginning in Rails 4, Rails ships with a `rails` binstub at ./bin/rails that
+should be used instead of the Bundler-generated `rails` binstub.
+
+If you are seeing this message, your binstub at ./bin/rails was generated by
+Bundler instead of Rails.
+
+You might need to regenerate your `rails` binstub locally and add it to source
+control:
+
+ rails app:update:bin # Bear in mind this generates other binstubs
+ # too that you may or may not want (like yarn)
-In Rails #{Rails::VERSION::MAJOR}, your app's bin/ directory contains executables that are versioned
-like any other source code, rather than stubs that are generated on demand.
+If you already have Rails binstubs in source control, you might be
+inadverently overwriting them during deployment by using bundle install
+with the --binstubs option.
-Here's how to upgrade:
+If your application was created prior to Rails 4, here's how to upgrade:
bundle config --delete bin # Turn off Bundler's stub generator
- rails app:update:bin # Use the new Rails 5 executables
+ rails app:update:bin # Use the new Rails executables
git add bin # Add bin/ to source control
You may need to remove bin/ from your .gitignore as well.
diff --git a/railties/lib/rails/app_updater.rb b/railties/lib/rails/app_updater.rb
new file mode 100644
index 0000000000..a076d082d5
--- /dev/null
+++ b/railties/lib/rails/app_updater.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+require "rails/generators"
+require "rails/generators/rails/app/app_generator"
+
+module Rails
+ class AppUpdater # :nodoc:
+ class << self
+ def invoke_from_app_generator(method)
+ app_generator.send(method)
+ end
+
+ def app_generator
+ @app_generator ||= begin
+ gen = Rails::Generators::AppGenerator.new ["rails"], generator_options, destination_root: Rails.root
+ File.exist?(Rails.root.join("config", "application.rb")) ? gen.send(:app_const) : gen.send(:valid_const?)
+ gen
+ end
+ end
+
+ private
+ def generator_options
+ options = { api: !!Rails.application.config.api_only, update: true }
+ options[:skip_active_record] = !defined?(ActiveRecord::Railtie)
+ options[:skip_active_storage] = !defined?(ActiveStorage::Engine) || !defined?(ActiveRecord::Railtie)
+ options[:skip_action_mailer] = !defined?(ActionMailer::Railtie)
+ options[:skip_action_cable] = !defined?(ActionCable::Engine)
+ options[:skip_sprockets] = !defined?(Sprockets::Railtie)
+ options[:skip_puma] = !defined?(Puma)
+ options
+ end
+ end
+ end
+end
diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb
index 39ca2db8e1..b1429df18b 100644
--- a/railties/lib/rails/application.rb
+++ b/railties/lib/rails/application.rb
@@ -1,8 +1,12 @@
+# frozen_string_literal: true
+
require "yaml"
require "active_support/core_ext/hash/keys"
require "active_support/core_ext/object/blank"
require "active_support/key_generator"
require "active_support/message_verifier"
+require "active_support/encrypted_configuration"
+require "active_support/deprecation"
require "rails/engine"
require "rails/secrets"
@@ -169,12 +173,9 @@ module Rails
# number of iterations selected based on consultation with the google security
# team. Details at https://github.com/rails/rails/pull/6952#issuecomment-7661220
@caching_key_generator ||=
- if secrets.secret_key_base
- unless secrets.secret_key_base.kind_of?(String)
- raise ArgumentError, "`secret_key_base` for #{Rails.env} environment must be a type of String, change this value in `config/secrets.yml`"
- end
- key_generator = ActiveSupport::KeyGenerator.new(secrets.secret_key_base, iterations: 1000)
- ActiveSupport::CachingKeyGenerator.new(key_generator)
+ if secret_key_base
+ ActiveSupport::CachingKeyGenerator.new \
+ ActiveSupport::KeyGenerator.new(secret_key_base, iterations: 1000)
else
ActiveSupport::LegacyKeyGenerator.new(secrets.secret_token)
end
@@ -244,13 +245,11 @@ module Rails
# will be used by middlewares and engines to configure themselves.
def env_config
@app_env_config ||= begin
- validate_secret_key_config!
-
super.merge(
"action_dispatch.parameter_filter" => config.filter_parameters,
"action_dispatch.redirect_filter" => config.filter_redirect,
"action_dispatch.secret_token" => secrets.secret_token,
- "action_dispatch.secret_key_base" => secrets.secret_key_base,
+ "action_dispatch.secret_key_base" => secret_key_base,
"action_dispatch.show_exceptions" => config.action_dispatch.show_exceptions,
"action_dispatch.show_detailed_exceptions" => config.consider_all_requests_local,
"action_dispatch.logger" => Rails.logger,
@@ -261,8 +260,12 @@ module Rails
"action_dispatch.encrypted_cookie_salt" => config.action_dispatch.encrypted_cookie_salt,
"action_dispatch.encrypted_signed_cookie_salt" => config.action_dispatch.encrypted_signed_cookie_salt,
"action_dispatch.authenticated_encrypted_cookie_salt" => config.action_dispatch.authenticated_encrypted_cookie_salt,
+ "action_dispatch.use_authenticated_cookie_encryption" => config.action_dispatch.use_authenticated_cookie_encryption,
+ "action_dispatch.encrypted_cookie_cipher" => config.action_dispatch.encrypted_cookie_cipher,
+ "action_dispatch.signed_cookie_digest" => config.action_dispatch.signed_cookie_digest,
"action_dispatch.cookies_serializer" => config.action_dispatch.cookies_serializer,
- "action_dispatch.cookies_digest" => config.action_dispatch.cookies_digest
+ "action_dispatch.cookies_digest" => config.action_dispatch.cookies_digest,
+ "action_dispatch.cookies_rotations" => config.action_dispatch.cookies_rotations
)
end
end
@@ -396,6 +399,11 @@ module Rails
# Fallback to config.secret_token if secrets.secret_token isn't set
secrets.secret_token ||= config.secret_token
+ if secrets.secret_token.present?
+ ActiveSupport::Deprecation.warn \
+ "`secrets.secret_token` is deprecated in favor of `secret_key_base` and will be removed in Rails 6.0."
+ end
+
secrets
end
end
@@ -404,6 +412,64 @@ module Rails
@secrets = secrets
end
+ # The secret_key_base is used as the input secret to the application's key generator, which in turn
+ # is used to create all MessageVerifiers/MessageEncryptors, including the ones that sign and encrypt cookies.
+ #
+ # In test and development, this is simply derived as a MD5 hash of the application's name.
+ #
+ # In all other environments, we look for it first in ENV["SECRET_KEY_BASE"],
+ # then credentials.secret_key_base, and finally secrets.secret_key_base. For most applications,
+ # the correct place to store it is in the encrypted credentials file.
+ def secret_key_base
+ if Rails.env.test? || Rails.env.development?
+ Digest::MD5.hexdigest self.class.name
+ else
+ validate_secret_key_base \
+ ENV["SECRET_KEY_BASE"] || credentials.secret_key_base || secrets.secret_key_base
+ end
+ end
+
+ # 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+.
+ def credentials
+ @credentials ||= encrypted("config/credentials.yml.enc")
+ end
+
+ # Shorthand to decrypt any encrypted configurations or files.
+ #
+ # For any file added with <tt>bin/rails encrypted:edit</tt> call +read+ to decrypt
+ # the file with the master key.
+ # The master key is either stored in +config/master.key+ or <tt>ENV["RAILS_MASTER_KEY"]</tt>.
+ #
+ # Rails.application.encrypted("config/mystery_man.txt.enc").read
+ # # => "We've met before, haven't we?"
+ #
+ # It's also possible to interpret encrypted YAML files with +config+.
+ #
+ # Rails.application.encrypted("config/credentials.yml.enc").config
+ # # => { next_guys_line: "I don't think so. Where was it you think we met?" }
+ #
+ # Any top-level configs are also accessible directly on the return value:
+ #
+ # Rails.application.encrypted("config/credentials.yml.enc").next_guys_line
+ # # => "I don't think so. Where was it you think we met?"
+ #
+ # The files or configs can also be encrypted with a custom key. To decrypt with
+ # a key in the +ENV+, use:
+ #
+ # Rails.application.encrypted("config/special_tokens.yml.enc", env_key: "SPECIAL_TOKENS")
+ #
+ # Or to decrypt with a file, that should be version control ignored, relative to +Rails.root+:
+ #
+ # Rails.application.encrypted("config/special_tokens.yml.enc", key_path: "config/special_tokens.key")
+ def encrypted(path, key_path: "config/master.key", env_key: "RAILS_MASTER_KEY")
+ ActiveSupport::EncryptedConfiguration.new \
+ config_path: Rails.root.join(path),
+ key_path: Rails.root.join(key_path),
+ env_key: env_key
+ end
+
def to_app #:nodoc:
self
end
@@ -502,14 +568,13 @@ module Rails
default_stack.build_stack
end
- def validate_secret_key_config! #:nodoc:
- if secrets.secret_key_base.blank?
- ActiveSupport::Deprecation.warn "You didn't set `secret_key_base`. " \
- "Read the upgrade documentation to learn more about this new config option."
-
- if secrets.secret_token.blank?
- raise "Missing `secret_key_base` for '#{Rails.env}' environment, set this value in `config/secrets.yml`"
- end
+ def validate_secret_key_base(secret_key_base)
+ if secret_key_base.is_a?(String) && secret_key_base.present?
+ secret_key_base
+ elsif secret_key_base
+ raise ArgumentError, "`secret_key_base` for #{Rails.env} environment must be a type of String`"
+ elsif secrets.secret_token.blank?
+ raise ArgumentError, "Missing `secret_key_base` for '#{Rails.env}' environment, set this string with `rails credentials:edit`"
end
end
diff --git a/railties/lib/rails/application/bootstrap.rb b/railties/lib/rails/application/bootstrap.rb
index dc0491035d..e3c0759f95 100644
--- a/railties/lib/rails/application/bootstrap.rb
+++ b/railties/lib/rails/application/bootstrap.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "fileutils"
require "active_support/notifications"
require "active_support/dependencies"
diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb
index 4ffde6198a..290ec13878 100644
--- a/railties/lib/rails/application/configuration.rb
+++ b/railties/lib/rails/application/configuration.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "active_support/core_ext/kernel/reporting"
require "active_support/file_update_checker"
require "rails/engine/configuration"
@@ -86,12 +88,24 @@ module Rails
if respond_to?(:active_record)
active_record.cache_versioning = true
+ # Remove the temporary load hook from SQLite3Adapter when this is removed
+ ActiveSupport.on_load(:active_record_sqlite3adapter) do
+ ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer = true
+ end
end
if respond_to?(:action_dispatch)
action_dispatch.use_authenticated_cookie_encryption = true
end
+ if respond_to?(:active_support)
+ active_support.use_authenticated_message_encryption = true
+ end
+
+ if respond_to?(:action_controller)
+ action_controller.default_protect_from_forgery = true
+ end
+
else
raise "Unknown version #{target_version.to_s.inspect}"
end
@@ -137,7 +151,7 @@ module Rails
end
# Loads and returns the entire raw configuration of database from
- # values stored in `config/database.yml`.
+ # values stored in <tt>config/database.yml</tt>.
def database_configuration
path = paths["config/database"].existent.first
yaml = Pathname.new(path) if path
diff --git a/railties/lib/rails/application/default_middleware_stack.rb b/railties/lib/rails/application/default_middleware_stack.rb
index 8fe48feefb..ea2273c1f2 100644
--- a/railties/lib/rails/application/default_middleware_stack.rb
+++ b/railties/lib/rails/application/default_middleware_stack.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Rails
class Application
class DefaultMiddlewareStack
@@ -10,7 +12,7 @@ module Rails
end
def build_stack
- ActionDispatch::MiddlewareStack.new.tap do |middleware|
+ ActionDispatch::MiddlewareStack.new do |middleware|
if config.force_ssl
middleware.use ::ActionDispatch::SSL, config.ssl_options
end
diff --git a/railties/lib/rails/application/finisher.rb b/railties/lib/rails/application/finisher.rb
index c027d06663..3d938be951 100644
--- a/railties/lib/rails/application/finisher.rb
+++ b/railties/lib/rails/application/finisher.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Rails
class Application
module Finisher
diff --git a/railties/lib/rails/application/routes_reloader.rb b/railties/lib/rails/application/routes_reloader.rb
index e02ef629f2..2ef09b4162 100644
--- a/railties/lib/rails/application/routes_reloader.rb
+++ b/railties/lib/rails/application/routes_reloader.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "active_support/core_ext/module/delegation"
module Rails
diff --git a/railties/lib/rails/application_controller.rb b/railties/lib/rails/application_controller.rb
index f7d112900a..fa8793d81a 100644
--- a/railties/lib/rails/application_controller.rb
+++ b/railties/lib/rails/application_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Rails::ApplicationController < ActionController::Base # :nodoc:
self.view_paths = File.expand_path("templates", __dir__)
layout "application"
diff --git a/railties/lib/rails/backtrace_cleaner.rb b/railties/lib/rails/backtrace_cleaner.rb
index 3bd18ebfb5..ae8db0f8ef 100644
--- a/railties/lib/rails/backtrace_cleaner.rb
+++ b/railties/lib/rails/backtrace_cleaner.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "active_support/backtrace_cleaner"
module Rails
diff --git a/railties/lib/rails/cli.rb b/railties/lib/rails/cli.rb
index 973b746068..e56e604fdc 100644
--- a/railties/lib/rails/cli.rb
+++ b/railties/lib/rails/cli.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rails/app_loader"
# If we are inside a Rails application this method performs an exec and thus
diff --git a/railties/lib/rails/code_statistics.rb b/railties/lib/rails/code_statistics.rb
index 70dce268f1..9c447c366f 100644
--- a/railties/lib/rails/code_statistics.rb
+++ b/railties/lib/rails/code_statistics.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rails/code_statistics_calculator"
require "active_support/core_ext/enumerable"
diff --git a/railties/lib/rails/code_statistics_calculator.rb b/railties/lib/rails/code_statistics_calculator.rb
index d0194af197..85f86bdbd0 100644
--- a/railties/lib/rails/code_statistics_calculator.rb
+++ b/railties/lib/rails/code_statistics_calculator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class CodeStatisticsCalculator #:nodoc:
attr_reader :lines, :code_lines, :classes, :methods
diff --git a/railties/lib/rails/command.rb b/railties/lib/rails/command.rb
index ee020b58f9..812e846837 100644
--- a/railties/lib/rails/command.rb
+++ b/railties/lib/rails/command.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "active_support"
require "active_support/dependencies/autoload"
require "active_support/core_ext/enumerable"
diff --git a/railties/lib/rails/command/actions.rb b/railties/lib/rails/command/actions.rb
index a00e58997c..cbb743346b 100644
--- a/railties/lib/rails/command/actions.rb
+++ b/railties/lib/rails/command/actions.rb
@@ -1,9 +1,11 @@
+# frozen_string_literal: true
+
module Rails
module Command
module Actions
- # Change to the application's path if there is no config.ru file in current directory.
- # This allows us to run `rails server` from other directories, but still get
- # the main config.ru and properly set the tmp directory.
+ # Change to the application's path if there is no <tt>config.ru</tt> file in current directory.
+ # This allows us to run <tt>rails server</tt> from other directories, but still get
+ # the main <tt>config.ru</tt> and properly set the <tt>tmp</tt> directory.
def set_application_directory!
Dir.chdir(File.expand_path("../..", APP_PATH)) unless File.exist?(File.expand_path("config.ru"))
end
diff --git a/railties/lib/rails/command/base.rb b/railties/lib/rails/command/base.rb
index 4f074df473..fa462ef7e9 100644
--- a/railties/lib/rails/command/base.rb
+++ b/railties/lib/rails/command/base.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "thor"
require "erb"
@@ -73,7 +75,7 @@ module Rails
# Use Rails' default banner.
def banner(*)
- "#{executable} #{arguments.map(&:usage).join(' ')} [options]".squish!
+ "#{executable} #{arguments.map(&:usage).join(' ')} [options]".squish
end
# Sets the base_name taking into account the current class namespace.
@@ -110,8 +112,8 @@ module Rails
# Default file root to place extra files a command might need, placed
# one folder above the command file.
#
- # For a `Rails::Command::TestCommand` placed in `rails/command/test_command.rb`
- # would return `rails/test`.
+ # For a Rails::Command::TestCommand placed in <tt>rails/command/test_command.rb</tt>
+ # would return <tt>rails/test</tt>.
def default_command_root
path = File.expand_path(File.join("../commands", command_root_namespace), __dir__)
path if File.exist?(path)
diff --git a/railties/lib/rails/command/behavior.rb b/railties/lib/rails/command/behavior.rb
index 4a92f72f16..7a6dd28e1a 100644
--- a/railties/lib/rails/command/behavior.rb
+++ b/railties/lib/rails/command/behavior.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "active_support"
module Rails
diff --git a/railties/lib/rails/command/environment_argument.rb b/railties/lib/rails/command/environment_argument.rb
index 05eac34155..5dc98b113d 100644
--- a/railties/lib/rails/command/environment_argument.rb
+++ b/railties/lib/rails/command/environment_argument.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "active_support"
module Rails
@@ -7,13 +9,24 @@ module Rails
included do
argument :environment, optional: true, banner: "environment"
+
+ class_option :environment, aliases: "-e", type: :string,
+ desc: "Specifies the environment to run this console under (test/development/production)."
end
private
def extract_environment_option_from_argument
if environment
self.options = options.merge(environment: acceptable_environment(environment))
- elsif !options[:environment]
+
+ ActiveSupport::Deprecation.warn "Passing the environment's name as a " \
+ "regular argument is deprecated and " \
+ "will be removed in the next Rails " \
+ "version. Please, use the -e option " \
+ "instead."
+ elsif options[:environment]
+ self.options = options.merge(environment: acceptable_environment(options[:environment]))
+ else
self.options = options.merge(environment: Rails::Command.environment)
end
end
diff --git a/railties/lib/rails/command/helpers/editor.rb b/railties/lib/rails/command/helpers/editor.rb
new file mode 100644
index 0000000000..6191d97672
--- /dev/null
+++ b/railties/lib/rails/command/helpers/editor.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+require "active_support/encrypted_file"
+
+module Rails
+ module Command
+ module Helpers
+ module Editor
+ private
+ def ensure_editor_available(command:)
+ if ENV["EDITOR"].to_s.empty?
+ say "No $EDITOR to open file in. Assign one like this:"
+ say ""
+ say %(EDITOR="mate --wait" #{command})
+ say ""
+ say "For editors that fork and exit immediately, it's important to pass a wait flag,"
+ say "otherwise the credentials will be saved immediately with no chance to edit."
+
+ false
+ else
+ true
+ end
+ end
+
+ def catch_editing_exceptions
+ yield
+ rescue Interrupt
+ say "Aborted changing file: nothing saved."
+ rescue ActiveSupport::EncryptedFile::MissingKeyError => error
+ say error.message
+ end
+ end
+ end
+ end
+end
diff --git a/railties/lib/rails/commands.rb b/railties/lib/rails/commands.rb
index fff0119c65..77961a0292 100644
--- a/railties/lib/rails/commands.rb
+++ b/railties/lib/rails/commands.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rails/command"
aliases = {
diff --git a/railties/lib/rails/commands/application/application_command.rb b/railties/lib/rails/commands/application/application_command.rb
index 7675d3b3d1..f77553b830 100644
--- a/railties/lib/rails/commands/application/application_command.rb
+++ b/railties/lib/rails/commands/application/application_command.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rails/generators"
require "rails/generators/rails/app/app_generator"
diff --git a/railties/lib/rails/commands/console/console_command.rb b/railties/lib/rails/commands/console/console_command.rb
index ec58540923..e35faa5b01 100644
--- a/railties/lib/rails/commands/console/console_command.rb
+++ b/railties/lib/rails/commands/console/console_command.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "irb"
require "irb/completion"
@@ -70,9 +72,6 @@ module Rails
class_option :sandbox, aliases: "-s", type: :boolean, default: false,
desc: "Rollback database modifications on exit."
- class_option :environment, aliases: "-e", type: :string,
- desc: "Specifies the environment to run this console under (test/development/production)."
-
def initialize(args = [], local_options = {}, config = {})
console_options = []
diff --git a/railties/lib/rails/commands/credentials/USAGE b/railties/lib/rails/commands/credentials/USAGE
new file mode 100644
index 0000000000..85877c71b7
--- /dev/null
+++ b/railties/lib/rails/commands/credentials/USAGE
@@ -0,0 +1,40 @@
+=== Storing Encrypted Credentials in Source Control
+
+The Rails `credentials` commands provide access to encrypted credentials,
+so you can safely store access tokens, database passwords, and the like
+safely inside the app without relying on a mess of ENVs.
+
+This also allows for atomic deploys: no need to coordinate key changes
+to get everything working as the keys are shipped with the code.
+
+=== Setup
+
+Applications after Rails 5.2 automatically have a basic credentials file generated
+that just contains the secret_key_base used by MessageVerifiers/MessageEncryptors, like the ones
+signing and encrypting cookies.
+
+For applications created prior to Rails 5.2, we'll automatically generate a new
+credentials file in `config/credentials.yml.enc` the first time you run `bin/rails credentials:edit`.
+If you didn't have a master key saved in `config/master.key`, that'll be created too.
+
+Don't lose this master key! Put it in a password manager your team can access.
+Should you lose it no one, including you, will be able to access any encrypted
+credentials.
+
+Don't commit the key! Add `config/master.key` to your source control's
+ignore file. If you use Git, Rails handles this for you.
+
+Rails also looks for the master key in `ENV["RAILS_MASTER_KEY"]`, if that's easier to manage.
+
+You could prepend that to your server's start command like this:
+
+ RAILS_MASTER_KEY="very-secret-and-secure" server.start
+
+=== Editing Credentials
+
+This will open a temporary file in `$EDITOR` with the decrypted contents to edit
+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.
diff --git a/railties/lib/rails/commands/credentials/credentials_command.rb b/railties/lib/rails/commands/credentials/credentials_command.rb
new file mode 100644
index 0000000000..8085f07c2b
--- /dev/null
+++ b/railties/lib/rails/commands/credentials/credentials_command.rb
@@ -0,0 +1,72 @@
+# frozen_string_literal: true
+
+require "active_support"
+require "rails/command/helpers/editor"
+
+module Rails
+ module Command
+ class CredentialsCommand < Rails::Command::Base # :nodoc:
+ include Helpers::Editor
+
+ no_commands do
+ def help
+ say "Usage:\n #{self.class.banner}"
+ say ""
+ say self.class.desc
+ end
+ end
+
+ def edit
+ require_application_and_environment!
+
+ ensure_editor_available(command: "bin/rails credentials:edit") || (return)
+ ensure_master_key_has_been_added
+ ensure_credentials_have_been_added
+
+ catch_editing_exceptions do
+ change_credentials_in_system_editor
+ end
+
+ say "New credentials encrypted and saved."
+ end
+
+ def show
+ require_application_and_environment!
+
+ say Rails.application.credentials.read.presence ||
+ "No credentials have been added yet. Use bin/rails credentials:edit to change that."
+ end
+
+ private
+ def ensure_master_key_has_been_added
+ master_key_generator.add_master_key_file
+ master_key_generator.ignore_master_key_file
+ end
+
+ def ensure_credentials_have_been_added
+ credentials_generator.add_credentials_file_silently
+ end
+
+ def change_credentials_in_system_editor
+ Rails.application.credentials.change do |tmp_path|
+ system("#{ENV["EDITOR"]} #{tmp_path}")
+ end
+ end
+
+
+ def master_key_generator
+ require "rails/generators"
+ require "rails/generators/rails/master_key/master_key_generator"
+
+ Rails::Generators::MasterKeyGenerator.new
+ end
+
+ def credentials_generator
+ require "rails/generators"
+ require "rails/generators/rails/credentials/credentials_generator"
+
+ Rails::Generators::CredentialsGenerator.new
+ end
+ end
+ end
+end
diff --git a/railties/lib/rails/commands/dbconsole/dbconsole_command.rb b/railties/lib/rails/commands/dbconsole/dbconsole_command.rb
index 5bfbe58d97..8df548b5de 100644
--- a/railties/lib/rails/commands/dbconsole/dbconsole_command.rb
+++ b/railties/lib/rails/commands/dbconsole/dbconsole_command.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rails/command/environment_argument"
module Rails
@@ -11,7 +13,7 @@ module Rails
end
def start
- ENV["RAILS_ENV"] = @options[:environment] || environment
+ ENV["RAILS_ENV"] ||= @options[:environment] || environment
case config["adapter"]
when /^(jdbc)?mysql/
@@ -58,7 +60,7 @@ module Rails
logon = ""
if config["username"]
- logon = config["username"]
+ logon = config["username"].dup
logon << "/#{config['password']}" if config["password"] && @options["include_password"]
logon << "@#{config['database']}" if config["database"]
end
@@ -73,7 +75,7 @@ module Rails
args += ["-P", "#{config['password']}"] if config["password"]
if config["host"]
- host_arg = "#{config['host']}"
+ host_arg = "#{config['host']}".dup
host_arg << ":#{config['port']}" if config["port"]
args += ["-S", host_arg]
end
@@ -87,10 +89,15 @@ module Rails
def config
@config ||= begin
- if configurations[environment].blank?
+ # We need to check whether the user passed the connection the
+ # first time around to show a consistent error message to people
+ # relying on 2-level database configuration.
+ if @options["connection"] && configurations[connection].blank?
+ raise ActiveRecord::AdapterNotSpecified, "'#{connection}' connection is not configured. Available configuration: #{configurations.inspect}"
+ elsif configurations[environment].blank? && configurations[connection].blank?
raise ActiveRecord::AdapterNotSpecified, "'#{environment}' database is not configured. Available configuration: #{configurations.inspect}"
else
- configurations[environment]
+ configurations[environment].presence || configurations[connection]
end
end
end
@@ -99,6 +106,10 @@ module Rails
Rails.respond_to?(:env) ? Rails.env : Rails::Command.environment
end
+ def connection
+ @options.fetch(:connection, "primary")
+ end
+
private
def configurations # :doc:
require APP_PATH
@@ -142,12 +153,16 @@ module Rails
class_option :header, type: :boolean
- class_option :environment, aliases: "-e", type: :string,
- desc: "Specifies the environment to run this console under (test/development/production)."
+ class_option :connection, aliases: "-c", type: :string,
+ desc: "Specifies the connection to use."
def perform
extract_environment_option_from_argument
+ # RAILS_ENV needs to be set before config/application is required.
+ ENV["RAILS_ENV"] = options[:environment]
+
+ require_application_and_environment!
Rails::DBConsole.start(options)
end
end
diff --git a/railties/lib/rails/commands/destroy/destroy_command.rb b/railties/lib/rails/commands/destroy/destroy_command.rb
index 281732a936..dd432d28fd 100644
--- a/railties/lib/rails/commands/destroy/destroy_command.rb
+++ b/railties/lib/rails/commands/destroy/destroy_command.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rails/generators"
module Rails
diff --git a/railties/lib/rails/commands/encrypted/encrypted_command.rb b/railties/lib/rails/commands/encrypted/encrypted_command.rb
new file mode 100644
index 0000000000..898094f1a4
--- /dev/null
+++ b/railties/lib/rails/commands/encrypted/encrypted_command.rb
@@ -0,0 +1,77 @@
+# frozen_string_literal: true
+
+require "pathname"
+require "active_support"
+require "rails/command/helpers/editor"
+
+module Rails
+ module Command
+ class EncryptedCommand < Rails::Command::Base # :nodoc:
+ include Helpers::Editor
+
+ class_option :key, aliases: "-k", type: :string,
+ default: "config/master.key", desc: "The Rails.root relative path to the encryption key"
+
+ no_commands do
+ def help
+ say "Usage:\n #{self.class.banner}"
+ say ""
+ end
+ end
+
+ def edit(file_path)
+ require_application_and_environment!
+
+ ensure_editor_available(command: "bin/rails encrypted:edit") || (return)
+ ensure_encryption_key_has_been_added(options[:key])
+ ensure_encrypted_file_has_been_added(file_path, options[:key])
+
+ catch_editing_exceptions do
+ change_encrypted_file_in_system_editor(file_path, options[:key])
+ end
+
+ say "File encrypted and saved."
+ rescue ActiveSupport::MessageEncryptor::InvalidMessage
+ say "Couldn't decrypt #{file_path}. Perhaps you passed the wrong key?"
+ end
+
+ def show(file_path)
+ require_application_and_environment!
+
+ say Rails.application.encrypted(file_path, key_path: options[:key]).read.presence ||
+ "File '#{file_path}' does not exist. Use bin/rails encrypted:edit #{file_path} to change that."
+ end
+
+ private
+ 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_encrypted_file_has_been_added(file_path, key_path)
+ encrypted_file_generator.add_encrypted_file_silently(file_path, key_path)
+ end
+
+ 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 encryption_key_file_generator
+ require "rails/generators"
+ require "rails/generators/rails/encryption_key_file/encryption_key_file_generator"
+
+ Rails::Generators::EncryptionKeyFileGenerator.new
+ end
+
+ def encrypted_file_generator
+ require "rails/generators"
+ require "rails/generators/rails/encrypted_file/encrypted_file_generator"
+
+ Rails::Generators::EncryptedFileGenerator.new
+ end
+ end
+ end
+end
diff --git a/railties/lib/rails/commands/generate/generate_command.rb b/railties/lib/rails/commands/generate/generate_command.rb
index 9dd7ad1012..93d7a0ce3a 100644
--- a/railties/lib/rails/commands/generate/generate_command.rb
+++ b/railties/lib/rails/commands/generate/generate_command.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rails/generators"
module Rails
diff --git a/railties/lib/rails/commands/help/help_command.rb b/railties/lib/rails/commands/help/help_command.rb
index 90d37217fc..8e5b4d68d3 100644
--- a/railties/lib/rails/commands/help/help_command.rb
+++ b/railties/lib/rails/commands/help/help_command.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Rails
module Command
class HelpCommand < Base # :nodoc:
diff --git a/railties/lib/rails/commands/new/new_command.rb b/railties/lib/rails/commands/new/new_command.rb
index 207dd5d995..d73d64d899 100644
--- a/railties/lib/rails/commands/new/new_command.rb
+++ b/railties/lib/rails/commands/new/new_command.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Rails
module Command
class NewCommand < Base # :nodoc:
diff --git a/railties/lib/rails/commands/plugin/plugin_command.rb b/railties/lib/rails/commands/plugin/plugin_command.rb
index b40ab006af..2b192abf9b 100644
--- a/railties/lib/rails/commands/plugin/plugin_command.rb
+++ b/railties/lib/rails/commands/plugin/plugin_command.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Rails
module Command
class PluginCommand < Base # :nodoc:
diff --git a/railties/lib/rails/commands/rake/rake_command.rb b/railties/lib/rails/commands/rake/rake_command.rb
index 075b1fd23d..535df0c430 100644
--- a/railties/lib/rails/commands/rake/rake_command.rb
+++ b/railties/lib/rails/commands/rake/rake_command.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Rails
module Command
class RakeCommand < Base # :nodoc:
diff --git a/railties/lib/rails/commands/runner/USAGE b/railties/lib/rails/commands/runner/USAGE
index b2a6e8493d..24b60037f0 100644
--- a/railties/lib/rails/commands/runner/USAGE
+++ b/railties/lib/rails/commands/runner/USAGE
@@ -8,6 +8,9 @@ Run the Ruby file located at `path/to/filename.rb` after loading the app:
<%= executable %> path/to/filename.rb
+Run the Ruby script read from stdin after loading the app:
+ <%= executable %> -
+
<% unless Gem.win_platform? %>
You can also use the runner command as a shebang line for your executables:
diff --git a/railties/lib/rails/commands/runner/runner_command.rb b/railties/lib/rails/commands/runner/runner_command.rb
index 6864a9726b..30fbf04982 100644
--- a/railties/lib/rails/commands/runner/runner_command.rb
+++ b/railties/lib/rails/commands/runner/runner_command.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Rails
module Command
class RunnerCommand < Base # :nodoc:
@@ -13,7 +15,7 @@ module Rails
end
def self.banner(*)
- "#{super} [<'Some.ruby(code)'> | <filename.rb>]"
+ "#{super} [<'Some.ruby(code)'> | <filename.rb> | -]"
end
def perform(code_or_file = nil, *command_argv)
@@ -29,12 +31,14 @@ module Rails
ARGV.replace(command_argv)
- if File.exist?(code_or_file)
+ if code_or_file == "-"
+ eval($stdin.read, TOPLEVEL_BINDING, "stdin")
+ elsif File.exist?(code_or_file)
$0 = code_or_file
Kernel.load code_or_file
else
begin
- eval(code_or_file, binding, __FILE__, __LINE__)
+ eval(code_or_file, TOPLEVEL_BINDING, __FILE__, __LINE__)
rescue SyntaxError, NameError => error
$stderr.puts "Please specify a valid ruby command or the path of a script to run."
$stderr.puts "Run '#{self.class.executable} -h' for help."
diff --git a/railties/lib/rails/commands/secrets/secrets_command.rb b/railties/lib/rails/commands/secrets/secrets_command.rb
index 651411d444..73a88767e2 100644
--- a/railties/lib/rails/commands/secrets/secrets_command.rb
+++ b/railties/lib/rails/commands/secrets/secrets_command.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "active_support"
require "rails/secrets"
@@ -13,7 +15,7 @@ module Rails
end
def setup
- generator.start
+ deprecate_in_favor_of_credentials_and_exit
end
def edit
@@ -31,7 +33,7 @@ module Rails
require_application_and_environment!
Rails::Secrets.read_for_editing do |tmp_path|
- system("\$EDITOR #{tmp_path}")
+ system("#{ENV["EDITOR"]} #{tmp_path}")
end
say "New secrets encrypted and saved."
@@ -40,20 +42,23 @@ module Rails
rescue Rails::Secrets::MissingKeyError => error
say error.message
rescue Errno::ENOENT => error
- raise unless error.message =~ /secrets\.yml\.enc/
-
- Rails::Secrets.read_template_for_editing do |tmp_path|
- system("\$EDITOR #{tmp_path}")
- generator.skip_secrets_file { setup }
+ if error.message =~ /secrets\.yml\.enc/
+ deprecate_in_favor_of_credentials_and_exit
+ else
+ raise
end
end
+ def show
+ say Rails::Secrets.read
+ end
+
private
- def generator
- require "rails/generators"
- require "rails/generators/rails/encrypted_secrets/encrypted_secrets_generator"
+ def deprecate_in_favor_of_credentials_and_exit
+ say "Encrypted secrets is deprecated in favor of credentials. Run:"
+ say "bin/rails credentials --help"
- Rails::Generators::EncryptedSecretsGenerator
+ exit 1
end
end
end
diff --git a/railties/lib/rails/commands/server/server_command.rb b/railties/lib/rails/commands/server/server_command.rb
index ebb4ae795a..703ec59087 100644
--- a/railties/lib/rails/commands/server/server_command.rb
+++ b/railties/lib/rails/commands/server/server_command.rb
@@ -1,7 +1,11 @@
+# frozen_string_literal: true
+
require "fileutils"
require "optparse"
require "action_dispatch"
require "rails"
+require "active_support/deprecation"
+require "active_support/core_ext/string/filters"
require "rails/dev_caching"
module Rails
@@ -18,10 +22,15 @@ module Rails
set_environment
end
- # TODO: this is no longer required but we keep it for the moment to support older config.ru files.
def app
@app ||= begin
app = super
+ if app.is_a?(Class)
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
+ Use `Rails::Application` subclass to start the server is deprecated and will be removed in Rails 6.0.
+ Please change `run #{app}` to `run Rails.application` in config.ru.
+ MSG
+ end
app.respond_to?(:to_app) ? app.to_app : app
end
end
@@ -64,9 +73,9 @@ module Rails
end
def print_boot_information
- url = "#{options[:SSLEnable] ? 'https' : 'http'}://#{options[:Host]}:#{options[:Port]}"
+ url = "on #{options[:SSLEnable] ? 'https' : 'http'}://#{options[:Host]}:#{options[:Port]}" unless use_puma?
puts "=> Booting #{ActiveSupport::Inflector.demodulize(server)}"
- puts "=> Rails #{Rails.version} application starting in #{Rails.env} on #{url}"
+ puts "=> Rails #{Rails.version} application starting in #{Rails.env} #{url}"
puts "=> Run `rails server -h` for more startup options"
end
@@ -91,6 +100,10 @@ module Rails
def restart_command
"bin/rails server #{ARGV.join(' ')}"
end
+
+ def use_puma?
+ server.to_s == "Rack::Handler::Puma"
+ end
end
module Command
@@ -113,6 +126,8 @@ module Rails
desc: "Specifies the PID file."
class_option "dev-caching", aliases: "-C", type: :boolean, default: nil,
desc: "Specifies whether to perform caching in development."
+ class_option "restart", type: :boolean, default: nil, hide: true
+ class_option "early_hints", type: :boolean, default: nil, desc: "Enables HTTP/2 early hints."
def initialize(args = [], local_options = {}, config = {})
@original_options = local_options
@@ -123,6 +138,7 @@ module Rails
def perform
set_application_directory!
+ prepare_restart
Rails::Server.new(server_options).tap do |server|
# Require application after server sets environment to propagate
# the --environment option.
@@ -146,7 +162,8 @@ module Rails
daemonize: options[:daemon],
pid: pid,
caching: options["dev-caching"],
- restart_cmd: restart_command
+ restart_cmd: restart_command,
+ early_hints: early_hints
}
end
end
@@ -209,7 +226,11 @@ module Rails
end
def restart_command
- "bin/rails server #{@server} #{@original_options.join(" ")}"
+ "bin/rails server #{@server} #{@original_options.join(" ")} --restart"
+ end
+
+ def early_hints
+ options[:early_hints]
end
def pid
@@ -219,6 +240,10 @@ module Rails
def self.banner(*)
"rails server [puma, thin etc] [options]"
end
+
+ def prepare_restart
+ FileUtils.rm_f(options[:pid]) if options[:restart]
+ end
end
end
end
diff --git a/railties/lib/rails/commands/test/test_command.rb b/railties/lib/rails/commands/test/test_command.rb
index 65e16900ba..00ea9ac4a6 100644
--- a/railties/lib/rails/commands/test/test_command.rb
+++ b/railties/lib/rails/commands/test/test_command.rb
@@ -1,21 +1,36 @@
+# frozen_string_literal: true
+
require "rails/command"
-require "rails/test_unit/minitest_plugin"
+require "rails/test_unit/runner"
+require "rails/test_unit/reporter"
module Rails
module Command
class TestCommand < Base # :nodoc:
no_commands do
def help
- perform # Hand over help printing to minitest.
+ say "Usage: #{Rails::TestUnitReporter.executable} [options] [files or directories]"
+ say ""
+ say "You can run a single test by appending a line number to a filename:"
+ say ""
+ say " #{Rails::TestUnitReporter.executable} test/models/user_test.rb:27"
+ say ""
+ say "You can run multiple files and directories at the same time:"
+ say ""
+ say " #{Rails::TestUnitReporter.executable} test/controllers test/integration/login_test.rb"
+ say ""
+ say "By default test failures and errors are reported inline during a run."
+ say ""
+
+ Minitest.run(%w(--help))
end
end
def perform(*)
- $LOAD_PATH << Rails::Command.root.join("test")
-
- Minitest.run_via = :rails
+ $LOAD_PATH << Rails::Command.root.join("test").to_s
- require "active_support/testing/autorun"
+ Rails::TestUnit::Runner.parse_options(ARGV)
+ Rails::TestUnit::Runner.run(ARGV)
end
end
end
diff --git a/railties/lib/rails/commands/version/version_command.rb b/railties/lib/rails/commands/version/version_command.rb
index ac745594ee..3e2112b6d4 100644
--- a/railties/lib/rails/commands/version/version_command.rb
+++ b/railties/lib/rails/commands/version/version_command.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Rails
module Command
class VersionCommand < Base # :nodoc:
diff --git a/railties/lib/rails/configuration.rb b/railties/lib/rails/configuration.rb
index fc7d4909f6..d3a54d9364 100644
--- a/railties/lib/rails/configuration.rb
+++ b/railties/lib/rails/configuration.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "active_support/ordered_options"
require "active_support/core_ext/object"
require "rails/paths"
diff --git a/railties/lib/rails/console/app.rb b/railties/lib/rails/console/app.rb
index affadc8e09..c37583ce9a 100644
--- a/railties/lib/rails/console/app.rb
+++ b/railties/lib/rails/console/app.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "active_support/all"
require "action_controller"
diff --git a/railties/lib/rails/console/helpers.rb b/railties/lib/rails/console/helpers.rb
index a33f71dc5b..39fbc55606 100644
--- a/railties/lib/rails/console/helpers.rb
+++ b/railties/lib/rails/console/helpers.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Rails
module ConsoleMethods
# Gets the helper methods available to the controller.
diff --git a/railties/lib/rails/dev_caching.rb b/railties/lib/rails/dev_caching.rb
index f69275a34a..ff629b2527 100644
--- a/railties/lib/rails/dev_caching.rb
+++ b/railties/lib/rails/dev_caching.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "fileutils"
module Rails
@@ -17,7 +19,6 @@ module Rails
end
FileUtils.touch "tmp/restart.txt"
- FileUtils.rm_f("tmp/pids/server.pid")
end
def enable_by_argument(caching)
diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb
index 2732485c5a..6a13a84108 100644
--- a/railties/lib/rails/engine.rb
+++ b/railties/lib/rails/engine.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rails/railtie"
require "rails/engine/railties"
require "active_support/core_ext/module/delegation"
diff --git a/railties/lib/rails/engine/commands.rb b/railties/lib/rails/engine/commands.rb
index b9ef63243a..05218640c6 100644
--- a/railties/lib/rails/engine/commands.rb
+++ b/railties/lib/rails/engine/commands.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
unless defined?(APP_PATH)
if File.exist?(File.expand_path("test/dummy/config/application.rb", ENGINE_ROOT))
APP_PATH = File.expand_path("test/dummy/config/application", ENGINE_ROOT)
diff --git a/railties/lib/rails/engine/configuration.rb b/railties/lib/rails/engine/configuration.rb
index 0c40173c38..6bf0406b21 100644
--- a/railties/lib/rails/engine/configuration.rb
+++ b/railties/lib/rails/engine/configuration.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rails/railtie/configuration"
module Rails
diff --git a/railties/lib/rails/engine/railties.rb b/railties/lib/rails/engine/railties.rb
index 9969a1475d..052b74c880 100644
--- a/railties/lib/rails/engine/railties.rb
+++ b/railties/lib/rails/engine/railties.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Rails
class Engine < Railtie
class Railties
diff --git a/railties/lib/rails/engine/updater.rb b/railties/lib/rails/engine/updater.rb
index 2ecf994a5c..be7a47124a 100644
--- a/railties/lib/rails/engine/updater.rb
+++ b/railties/lib/rails/engine/updater.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rails/generators"
require "rails/generators/rails/plugin/plugin_generator"
@@ -7,7 +9,7 @@ module Rails
class << self
def generator
@generator ||= Rails::Generators::PluginGenerator.new ["plugin"],
- { engine: true }, destination_root: ENGINE_ROOT
+ { engine: true }, { destination_root: ENGINE_ROOT }
end
def run(action)
diff --git a/railties/lib/rails/gem_version.rb b/railties/lib/rails/gem_version.rb
index 7bacf2e0ba..92b5e0392a 100644
--- a/railties/lib/rails/gem_version.rb
+++ b/railties/lib/rails/gem_version.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Rails
# Returns the version of the currently loaded Rails as a <tt>Gem::Version</tt>
def self.gem_version
diff --git a/railties/lib/rails/generators.rb b/railties/lib/rails/generators.rb
index 8f15f3a594..6c9c109f17 100644
--- a/railties/lib/rails/generators.rb
+++ b/railties/lib/rails/generators.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
activesupport_path = File.expand_path("../../../activesupport/lib", __dir__)
$:.unshift(activesupport_path) if File.directory?(activesupport_path) && !$:.include?(activesupport_path)
@@ -10,6 +12,7 @@ require "active_support/core_ext/kernel/singleton_class"
require "active_support/core_ext/array/extract_options"
require "active_support/core_ext/hash/deep_merge"
require "active_support/core_ext/module/attribute_accessors"
+require "active_support/core_ext/string/indent"
require "active_support/core_ext/string/inflections"
module Rails
@@ -215,6 +218,7 @@ module Rails
rails.delete("app")
rails.delete("plugin")
rails.delete("encrypted_secrets")
+ rails.delete("credentials")
hidden_namespaces.each { |n| groups.delete(n.to_s) }
@@ -270,8 +274,9 @@ module Rails
else
options = sorted_groups.flat_map(&:last)
suggestions = options.sort_by { |suggested| levenshtein_distance(namespace.to_s, suggested) }.first(3)
- msg = "Could not find generator '#{namespace}'. "
- msg << "Maybe you meant #{ suggestions.map { |s| "'#{s}'" }.to_sentence(last_word_connector: " or ", locale: :en) }\n"
+ suggestions.map! { |s| "'#{s}'" }
+ msg = "Could not find generator '#{namespace}'. ".dup
+ msg << "Maybe you meant #{ suggestions[0...-1].join(', ')} or #{suggestions[-1]}\n"
msg << "Run `rails generate --help` for more options."
puts msg
end
diff --git a/railties/lib/rails/generators/actions.rb b/railties/lib/rails/generators/actions.rb
index 0bd0615b7e..3362bf629a 100644
--- a/railties/lib/rails/generators/actions.rb
+++ b/railties/lib/rails/generators/actions.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Rails
module Generators
module Actions
@@ -11,17 +13,22 @@ module Rails
#
# gem "rspec", group: :test
# gem "technoweenie-restful-authentication", lib: "restful-authentication", source: "http://gems.github.com/"
- # gem "rails", "3.0", git: "git://github.com/rails/rails"
+ # gem "rails", "3.0", git: "https://github.com/rails/rails"
+ # gem "RedCloth", ">= 4.1.0", "< 4.2.0"
def gem(*args)
options = args.extract_options!
- name, version = args
+ name, *versions = args
# Set the message to be shown in logs. Uses the git repo if one is given,
# otherwise use name (version).
parts, message = [ quote(name) ], name.dup
- if version ||= options.delete(:version)
- parts << quote(version)
- message << " (#{version})"
+
+ if versions = versions.any? ? versions : options.delete(:version)
+ _versions = Array(versions)
+ _versions.each do |version|
+ parts << quote(version)
+ end
+ message << " (#{_versions.join(", ")})"
end
message = options[:git] if options[:git]
@@ -97,16 +104,16 @@ module Rails
# "config.action_controller.asset_host = 'localhost:3000'"
# end
def environment(data = nil, options = {})
- sentinel = /class [a-z_:]+ < Rails::Application/i
- env_file_sentinel = /Rails\.application\.configure do/
- data = yield if !data && block_given?
+ sentinel = "class Application < Rails::Application\n"
+ env_file_sentinel = "Rails.application.configure do\n"
+ data ||= yield if block_given?
in_root do
if options[:env].nil?
- inject_into_file "config/application.rb", "\n #{data}", after: sentinel, verbose: false
+ inject_into_file "config/application.rb", optimize_indentation(data, 4), after: sentinel, verbose: false
else
Array(options[:env]).each do |env|
- inject_into_file "config/environments/#{env}.rb", "\n #{data}", after: env_file_sentinel, verbose: false
+ inject_into_file "config/environments/#{env}.rb", optimize_indentation(data, 2), after: env_file_sentinel, verbose: false
end
end
end
@@ -137,12 +144,13 @@ module Rails
# end
#
# vendor("foreign.rb", "# Foreign code is fun")
- def vendor(filename, data = nil, &block)
+ def vendor(filename, data = nil)
log :vendor, filename
- create_file("vendor/#{filename}", data, verbose: false, &block)
+ data ||= yield if block_given?
+ create_file("vendor/#{filename}", optimize_indentation(data), verbose: false)
end
- # Create a new file in the lib/ directory. Code can be specified
+ # Create a new file in the <tt>lib/</tt> directory. Code can be specified
# in a block or a data string can be given.
#
# lib("crypto.rb") do
@@ -150,9 +158,10 @@ module Rails
# end
#
# lib("foreign.rb", "# Foreign code is fun")
- def lib(filename, data = nil, &block)
+ def lib(filename, data = nil)
log :lib, filename
- create_file("lib/#{filename}", data, verbose: false, &block)
+ data ||= yield if block_given?
+ create_file("lib/#{filename}", optimize_indentation(data), verbose: false)
end
# Create a new +Rakefile+ with the provided code (either in a block or a string).
@@ -170,9 +179,10 @@ module Rails
# end
#
# rakefile('seed.rake', 'puts "Planting seeds"')
- def rakefile(filename, data = nil, &block)
+ def rakefile(filename, data = nil)
log :rakefile, filename
- create_file("lib/tasks/#{filename}", data, verbose: false, &block)
+ data ||= yield if block_given?
+ create_file("lib/tasks/#{filename}", optimize_indentation(data), verbose: false)
end
# Create a new initializer with the provided code (either in a block or a string).
@@ -188,9 +198,10 @@ module Rails
# end
#
# initializer("api.rb", "API_KEY = '123456'")
- def initializer(filename, data = nil, &block)
+ def initializer(filename, data = nil)
log :initializer, filename
- create_file("config/initializers/#{filename}", data, verbose: false, &block)
+ data ||= yield if block_given?
+ create_file("config/initializers/#{filename}", optimize_indentation(data), verbose: false)
end
# Generate something using a generator from Rails or a plugin.
@@ -210,15 +221,17 @@ module Rails
# rake("db:migrate")
# rake("db:migrate", env: "production")
# rake("gems:install", sudo: true)
+ # rake("gems:install", capture: true)
def rake(command, options = {})
execute_command :rake, command, options
end
# Runs the supplied rake task (invoked with 'rails ...')
#
- # rails("db:migrate")
- # rails("db:migrate", env: "production")
- # rails("gems:install", sudo: true)
+ # rails_command("db:migrate")
+ # rails_command("db:migrate", env: "production")
+ # rails_command("gems:install", sudo: true)
+ # rails_command("gems:install", capture: true)
def rails_command(command, options = {})
execute_command :rails, command, options
end
@@ -227,6 +240,7 @@ module Rails
#
# capify!
def capify!
+ ActiveSupport::Deprecation.warn("`capify!` is deprecated and will be removed in the next version of Rails.")
log :capify, ""
in_root { run("#{extify(:capify)} .", verbose: false) }
end
@@ -239,7 +253,7 @@ module Rails
sentinel = /\.routes\.draw do\s*\n/m
in_root do
- inject_into_file "config/routes.rb", " #{routing_code}\n", after: sentinel, verbose: false, force: false
+ inject_into_file "config/routes.rb", optimize_indentation(routing_code, 2), after: sentinel, verbose: false, force: false
end
end
@@ -280,7 +294,11 @@ module Rails
log executor, command
env = options[:env] || ENV["RAILS_ENV"] || "development"
sudo = options[:sudo] && !Gem.win_platform? ? "sudo " : ""
- in_root { run("#{sudo}#{extify(executor)} #{command} RAILS_ENV=#{env}", verbose: false) }
+ config = { verbose: false }
+
+ config.merge!(capture: options[:capture]) if options[:capture]
+
+ in_root { run("#{sudo}#{extify(executor)} #{command} RAILS_ENV=#{env}", config) }
end
# Add an extension to the given name based on the platform.
@@ -303,6 +321,17 @@ module Rails
"'#{value}'"
end
end
+
+ # Returns optimized string with indentation
+ def optimize_indentation(value, amount = 0) # :doc:
+ return "#{value}\n" unless value.is_a?(String)
+
+ if value.lines.size > 1
+ value.strip_heredoc.indent(amount)
+ else
+ "#{value.strip.indent(amount)}\n"
+ end
+ end
end
end
end
diff --git a/railties/lib/rails/generators/actions/create_migration.rb b/railties/lib/rails/generators/actions/create_migration.rb
index d06609e91e..05bc242447 100644
--- a/railties/lib/rails/generators/actions/create_migration.rb
+++ b/railties/lib/rails/generators/actions/create_migration.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "fileutils"
require "thor/actions"
diff --git a/railties/lib/rails/generators/active_model.rb b/railties/lib/rails/generators/active_model.rb
index 2679d06fe4..8df8eb2438 100644
--- a/railties/lib/rails/generators/active_model.rb
+++ b/railties/lib/rails/generators/active_model.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Rails
module Generators
# ActiveModel is a class to be implemented by each ORM to allow Rails to
diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb
index 8429b6c7b8..73256bec61 100644
--- a/railties/lib/rails/generators/app_base.rb
+++ b/railties/lib/rails/generators/app_base.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "fileutils"
require "digest/md5"
require "active_support/core_ext/string/strip"
@@ -24,75 +26,78 @@ module Rails
end
def self.add_shared_options_for(name)
- class_option :template, type: :string, aliases: "-m",
- desc: "Path to some #{name} template (can be a filesystem path or URL)"
+ class_option :template, type: :string, aliases: "-m",
+ desc: "Path to some #{name} template (can be a filesystem path or URL)"
+
+ class_option :database, type: :string, aliases: "-d", default: "sqlite3",
+ desc: "Preconfigure for selected database (options: #{DATABASES.join('/')})"
- class_option :database, type: :string, aliases: "-d", default: "sqlite3",
- desc: "Preconfigure for selected database (options: #{DATABASES.join('/')})"
+ class_option :skip_yarn, type: :boolean, default: false,
+ desc: "Don't use Yarn for managing JavaScript dependencies"
- class_option :skip_yarn, type: :boolean, default: false,
- desc: "Don't use Yarn for managing JavaScript dependencies"
+ class_option :skip_gemfile, type: :boolean, default: false,
+ desc: "Don't create a Gemfile"
- class_option :skip_gemfile, type: :boolean, default: false,
- desc: "Don't create a Gemfile"
+ class_option :skip_git, type: :boolean, aliases: "-G", default: false,
+ desc: "Skip .gitignore file"
- class_option :skip_git, type: :boolean, aliases: "-G", default: false,
- desc: "Skip .gitignore file"
+ class_option :skip_keeps, type: :boolean, default: false,
+ desc: "Skip source control .keep files"
- class_option :skip_keeps, type: :boolean, default: false,
- desc: "Skip source control .keep files"
+ class_option :skip_action_mailer, type: :boolean, aliases: "-M",
+ default: false,
+ desc: "Skip Action Mailer files"
- class_option :skip_action_mailer, type: :boolean, aliases: "-M",
- default: false,
- desc: "Skip Action Mailer files"
+ class_option :skip_active_record, type: :boolean, aliases: "-O", default: false,
+ desc: "Skip Active Record files"
- class_option :skip_active_record, type: :boolean, aliases: "-O", default: false,
- desc: "Skip Active Record files"
+ class_option :skip_active_storage, type: :boolean, default: false,
+ desc: "Skip Active Storage files"
- class_option :skip_puma, type: :boolean, aliases: "-P", default: false,
- desc: "Skip Puma related files"
+ class_option :skip_puma, type: :boolean, aliases: "-P", default: false,
+ desc: "Skip Puma related files"
- class_option :skip_action_cable, type: :boolean, aliases: "-C", default: false,
- desc: "Skip Action Cable files"
+ class_option :skip_action_cable, type: :boolean, aliases: "-C", default: false,
+ desc: "Skip Action Cable files"
- class_option :skip_sprockets, type: :boolean, aliases: "-S", default: false,
- desc: "Skip Sprockets files"
+ class_option :skip_sprockets, type: :boolean, aliases: "-S", default: false,
+ desc: "Skip Sprockets files"
- class_option :skip_spring, type: :boolean, default: false,
- desc: "Don't install Spring application preloader"
+ class_option :skip_spring, type: :boolean, default: false,
+ desc: "Don't install Spring application preloader"
- class_option :skip_listen, type: :boolean, default: false,
- desc: "Don't generate configuration that depends on the listen gem"
+ 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_coffee, type: :boolean, default: false,
+ desc: "Don't use CoffeeScript"
- class_option :skip_javascript, type: :boolean, aliases: "-J", default: false,
- desc: "Skip JavaScript files"
+ class_option :skip_javascript, type: :boolean, aliases: "-J", default: false,
+ desc: "Skip JavaScript files"
- class_option :skip_turbolinks, type: :boolean, default: false,
- desc: "Skip turbolinks gem"
+ class_option :skip_turbolinks, type: :boolean, default: false,
+ desc: "Skip turbolinks gem"
- class_option :skip_test, type: :boolean, aliases: "-T", default: false,
- desc: "Skip test files"
+ class_option :skip_test, type: :boolean, aliases: "-T", default: false,
+ desc: "Skip test files"
- class_option :skip_system_test, type: :boolean, default: false,
- desc: "Skip system test files"
+ class_option :skip_system_test, type: :boolean, default: false,
+ desc: "Skip system test files"
- class_option :dev, type: :boolean, default: false,
- desc: "Setup the #{name} with Gemfile pointing to your Rails checkout"
+ class_option :dev, type: :boolean, default: false,
+ desc: "Setup the #{name} with Gemfile pointing to your Rails checkout"
- class_option :edge, type: :boolean, default: false,
- desc: "Setup the #{name} with Gemfile pointing to Rails repository"
+ class_option :edge, type: :boolean, default: false,
+ desc: "Setup the #{name} with Gemfile pointing to Rails repository"
- class_option :rc, type: :string, default: nil,
- desc: "Path to file containing extra configuration options for rails command"
+ class_option :rc, type: :string, default: nil,
+ desc: "Path to file containing extra configuration options for rails command"
- class_option :no_rc, type: :boolean, default: false,
- desc: "Skip loading of extra configuration options from .railsrc file"
+ class_option :no_rc, type: :boolean, default: false,
+ desc: "Skip loading of extra configuration options from .railsrc file"
- class_option :help, type: :boolean, aliases: "-h", group: :rails,
- desc: "Show this help message and quit"
+ class_option :help, type: :boolean, aliases: "-h", group: :rails,
+ desc: "Show this help message and quit"
end
def initialize(*args)
@@ -191,11 +196,29 @@ module Rails
end
def include_all_railties? # :doc:
- options.values_at(:skip_active_record, :skip_action_mailer, :skip_test, :skip_sprockets, :skip_action_cable).none?
+ [
+ options.values_at(
+ :skip_active_record,
+ :skip_action_mailer,
+ :skip_test,
+ :skip_sprockets,
+ :skip_action_cable
+ ),
+ skip_active_storage?
+ ].flatten.none?
end
def comment_if(value) # :doc:
- options[value] ? "# " : ""
+ question = "#{value}?"
+
+ comment =
+ if respond_to?(question, true)
+ send(question)
+ else
+ options[value]
+ end
+
+ comment ? "# " : ""
end
def keeps? # :doc:
@@ -206,6 +229,10 @@ module Rails
!options[:skip_active_record] && options[:database] == "sqlite3"
end
+ def skip_active_storage? # :doc:
+ options[:skip_active_storage] || options[:skip_active_record]
+ end
+
class GemfileEntry < Struct.new(:name, :version, :comment, :options, :commented_out)
def initialize(name, version, comment, options = {}, commented_out = false)
super
@@ -239,17 +266,14 @@ module Rails
end
def rails_gemfile_entry
- dev_edge_common = [
- GemfileEntry.github("arel", "rails/arel"),
- ]
if options.dev?
[
GemfileEntry.path("rails", Rails::Generators::RAILS_DEV_PATH)
- ] + dev_edge_common
+ ]
elsif options.edge?
[
GemfileEntry.github("rails", "rails/rails")
- ] + dev_edge_common
+ ]
else
[GemfileEntry.version("rails",
rails_version_specifier,
@@ -348,6 +372,8 @@ module Rails
comment = "See https://github.com/rails/execjs#readme for more supported runtimes"
if defined?(JRUBY_VERSION)
GemfileEntry.version "therubyrhino", nil, comment
+ elsif RUBY_PLATFORM =~ /mingw|mswin/
+ GemfileEntry.version "duktape", nil, comment
else
GemfileEntry.new "mini_racer", nil, comment, { platforms: :ruby }, true
end
@@ -365,7 +391,7 @@ module Rails
return [] if options[:skip_action_cable]
comment = "Use Redis adapter to run Action Cable in production"
gems = []
- gems << GemfileEntry.new("redis", "~> 3.0", comment, {}, true)
+ gems << GemfileEntry.new("redis", "~> 4.0", comment, {}, true)
gems
end
@@ -430,6 +456,16 @@ module Rails
end
end
+ def run_active_storage
+ unless skip_active_storage?
+ if bundle_install?
+ rails_command "active_storage:install", capture: options[:quiet]
+ else
+ log("Active Storage installation was skipped. Please run `bin/rails active_storage:install` to install Active Storage files.")
+ end
+ end
+ end
+
def empty_directory_with_keep_file(destination, config = {})
empty_directory(destination, config)
keep_file(destination)
diff --git a/railties/lib/rails/generators/base.rb b/railties/lib/rails/generators/base.rb
index e7f51dba99..5523a3f659 100644
--- a/railties/lib/rails/generators/base.rb
+++ b/railties/lib/rails/generators/base.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
begin
require "thor/group"
rescue LoadError
@@ -16,6 +18,9 @@ module Rails
include Thor::Actions
include Rails::Generators::Actions
+ class_option :skip_namespace, type: :boolean, default: false,
+ desc: "Skip namespace (affects only isolated applications)"
+
add_runtime_options!
strict_args_position!
@@ -271,6 +276,40 @@ module Rails
end
end
+ # Wrap block with namespace of current application
+ # if namespace exists and is not skipped
+ def module_namespacing(&block) # :doc:
+ content = capture(&block)
+ content = wrap_with_namespace(content) if namespaced?
+ concat(content)
+ end
+
+ def indent(content, multiplier = 2) # :doc:
+ spaces = " " * multiplier
+ content.each_line.map { |line| line.blank? ? line : "#{spaces}#{line}" }.join
+ end
+
+ def wrap_with_namespace(content) # :doc:
+ content = indent(content).chomp
+ "module #{namespace.name}\n#{content}\nend\n"
+ end
+
+ def namespace # :doc:
+ Rails::Generators.namespace
+ end
+
+ def namespaced? # :doc:
+ !options[:skip_namespace] && namespace
+ end
+
+ def namespace_dirs
+ @namespace_dirs ||= namespace.name.split("::").map(&:underscore)
+ end
+
+ def namespaced_path # :doc:
+ @namespaced_path ||= namespace_dirs.join("/")
+ end
+
# Use Rails default banner.
def self.banner # :doc:
"rails generate #{namespace.sub(/^rails:/, '')} #{arguments.map(&:usage).join(' ')} [options]".gsub(/\s+/, " ")
diff --git a/railties/lib/rails/generators/css/assets/assets_generator.rb b/railties/lib/rails/generators/css/assets/assets_generator.rb
index af7b5cf609..f657d1e50f 100644
--- a/railties/lib/rails/generators/css/assets/assets_generator.rb
+++ b/railties/lib/rails/generators/css/assets/assets_generator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rails/generators/named_base"
module Css # :nodoc:
diff --git a/railties/lib/rails/generators/css/scaffold/scaffold_generator.rb b/railties/lib/rails/generators/css/scaffold/scaffold_generator.rb
index cf534030f9..89c560f382 100644
--- a/railties/lib/rails/generators/css/scaffold/scaffold_generator.rb
+++ b/railties/lib/rails/generators/css/scaffold/scaffold_generator.rb
@@ -1,15 +1,17 @@
+# frozen_string_literal: true
+
require "rails/generators/named_base"
module Css # :nodoc:
module Generators # :nodoc:
class ScaffoldGenerator < Rails::Generators::NamedBase # :nodoc:
+ source_root Rails::Generators::ScaffoldGenerator.source_root
+
# In order to allow the Sass generators to pick up the default Rails CSS and
# transform it, we leave it in a standard location for the CSS stylesheet
# generators to handle. For the simple, default case, just copy it over.
def copy_stylesheet
- dir = Rails::Generators::ScaffoldGenerator.source_root
- file = File.join(dir, "scaffold.css")
- create_file "app/assets/stylesheets/scaffold.css", File.read(file)
+ copy_file "scaffold.css", "app/assets/stylesheets/scaffold.css"
end
end
end
diff --git a/railties/lib/rails/generators/erb.rb b/railties/lib/rails/generators/erb.rb
index 97d9ab29d4..ba20bcd32a 100644
--- a/railties/lib/rails/generators/erb.rb
+++ b/railties/lib/rails/generators/erb.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rails/generators/named_base"
module Erb # :nodoc:
diff --git a/railties/lib/rails/generators/erb/controller/controller_generator.rb b/railties/lib/rails/generators/erb/controller/controller_generator.rb
index 36ecfea09b..8e13744b2a 100644
--- a/railties/lib/rails/generators/erb/controller/controller_generator.rb
+++ b/railties/lib/rails/generators/erb/controller/controller_generator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rails/generators/erb"
module Erb # :nodoc:
diff --git a/railties/lib/rails/generators/erb/controller/templates/view.html.erb b/railties/lib/rails/generators/erb/controller/templates/view.html.erb.tt
index cd54d13d83..cd54d13d83 100644
--- a/railties/lib/rails/generators/erb/controller/templates/view.html.erb
+++ b/railties/lib/rails/generators/erb/controller/templates/view.html.erb.tt
diff --git a/railties/lib/rails/generators/erb/mailer/mailer_generator.rb b/railties/lib/rails/generators/erb/mailer/mailer_generator.rb
index 3f1d9932f6..e2ea66415f 100644
--- a/railties/lib/rails/generators/erb/mailer/mailer_generator.rb
+++ b/railties/lib/rails/generators/erb/mailer/mailer_generator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rails/generators/erb"
module Erb # :nodoc:
diff --git a/railties/lib/rails/generators/erb/mailer/templates/view.html.erb b/railties/lib/rails/generators/erb/mailer/templates/view.html.erb.tt
index b5045671b3..b5045671b3 100644
--- a/railties/lib/rails/generators/erb/mailer/templates/view.html.erb
+++ b/railties/lib/rails/generators/erb/mailer/templates/view.html.erb.tt
diff --git a/railties/lib/rails/generators/erb/mailer/templates/view.text.erb b/railties/lib/rails/generators/erb/mailer/templates/view.text.erb.tt
index 342285df19..342285df19 100644
--- a/railties/lib/rails/generators/erb/mailer/templates/view.text.erb
+++ b/railties/lib/rails/generators/erb/mailer/templates/view.text.erb.tt
diff --git a/railties/lib/rails/generators/erb/scaffold/scaffold_generator.rb b/railties/lib/rails/generators/erb/scaffold/scaffold_generator.rb
index 0d77ef21da..2fc04e4094 100644
--- a/railties/lib/rails/generators/erb/scaffold/scaffold_generator.rb
+++ b/railties/lib/rails/generators/erb/scaffold/scaffold_generator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rails/generators/erb"
require "rails/generators/resource_helpers"
diff --git a/railties/lib/rails/generators/erb/scaffold/templates/_form.html.erb b/railties/lib/rails/generators/erb/scaffold/templates/_form.html.erb.tt
index 4f2e84f924..0eb9d82bbb 100644
--- a/railties/lib/rails/generators/erb/scaffold/templates/_form.html.erb
+++ b/railties/lib/rails/generators/erb/scaffold/templates/_form.html.erb.tt
@@ -1,4 +1,4 @@
-<%%= form_with(model: <%= singular_table_name %>, local: true) do |form| %>
+<%%= form_with(model: <%= model_resource_name %>, local: true) do |form| %>
<%% if <%= singular_table_name %>.errors.any? %>
<div id="error_explanation">
<h2><%%= pluralize(<%= singular_table_name %>.errors.count, "error") %> prohibited this <%= singular_table_name %> from being saved:</h2>
diff --git a/railties/lib/rails/generators/erb/scaffold/templates/edit.html.erb b/railties/lib/rails/generators/erb/scaffold/templates/edit.html.erb.tt
index 81329473d9..81329473d9 100644
--- a/railties/lib/rails/generators/erb/scaffold/templates/edit.html.erb
+++ b/railties/lib/rails/generators/erb/scaffold/templates/edit.html.erb.tt
diff --git a/railties/lib/rails/generators/erb/scaffold/templates/index.html.erb b/railties/lib/rails/generators/erb/scaffold/templates/index.html.erb.tt
index 5f4904fee1..e1ede7c713 100644
--- a/railties/lib/rails/generators/erb/scaffold/templates/index.html.erb
+++ b/railties/lib/rails/generators/erb/scaffold/templates/index.html.erb.tt
@@ -18,9 +18,9 @@
<% attributes.reject(&:password_digest?).each do |attribute| -%>
<td><%%= <%= singular_table_name %>.<%= attribute.name %> %></td>
<% end -%>
- <td><%%= link_to 'Show', <%= singular_table_name %> %></td>
- <td><%%= link_to 'Edit', edit_<%= singular_table_name %>_path(<%= singular_table_name %>) %></td>
- <td><%%= link_to 'Destroy', <%= singular_table_name %>, method: :delete, data: { confirm: 'Are you sure?' } %></td>
+ <td><%%= link_to 'Show', <%= model_resource_name %> %></td>
+ <td><%%= link_to 'Edit', edit_<%= singular_route_name %>_path(<%= singular_table_name %>) %></td>
+ <td><%%= link_to 'Destroy', <%= model_resource_name %>, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<%% end %>
</tbody>
@@ -28,4 +28,4 @@
<br>
-<%%= link_to 'New <%= singular_table_name.titleize %>', new_<%= singular_table_name %>_path %>
+<%%= link_to 'New <%= singular_table_name.titleize %>', new_<%= singular_route_name %>_path %>
diff --git a/railties/lib/rails/generators/erb/scaffold/templates/new.html.erb b/railties/lib/rails/generators/erb/scaffold/templates/new.html.erb.tt
index 9b2b2f4875..9b2b2f4875 100644
--- a/railties/lib/rails/generators/erb/scaffold/templates/new.html.erb
+++ b/railties/lib/rails/generators/erb/scaffold/templates/new.html.erb.tt
diff --git a/railties/lib/rails/generators/erb/scaffold/templates/show.html.erb b/railties/lib/rails/generators/erb/scaffold/templates/show.html.erb.tt
index 5e634153be..5e634153be 100644
--- a/railties/lib/rails/generators/erb/scaffold/templates/show.html.erb
+++ b/railties/lib/rails/generators/erb/scaffold/templates/show.html.erb.tt
diff --git a/railties/lib/rails/generators/generated_attribute.rb b/railties/lib/rails/generators/generated_attribute.rb
index baed7bf1e3..2728459968 100644
--- a/railties/lib/rails/generators/generated_attribute.rb
+++ b/railties/lib/rails/generators/generated_attribute.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "active_support/time"
module Rails
@@ -151,7 +153,7 @@ module Rails
end
def inject_options
- "".tap { |s| options_for_migration.each { |k, v| s << ", #{k}: #{v.inspect}" } }
+ "".dup.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
index 52a71b58cd..9d32c666dc 100644
--- a/railties/lib/rails/generators/js/assets/assets_generator.rb
+++ b/railties/lib/rails/generators/js/assets/assets_generator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rails/generators/named_base"
module Js # :nodoc:
diff --git a/railties/lib/rails/generators/migration.rb b/railties/lib/rails/generators/migration.rb
index 82481169c3..1cbccfe461 100644
--- a/railties/lib/rails/generators/migration.rb
+++ b/railties/lib/rails/generators/migration.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "active_support/concern"
require "rails/generators/actions/create_migration"
diff --git a/railties/lib/rails/generators/model_helpers.rb b/railties/lib/rails/generators/model_helpers.rb
index 6f87a18660..50078404b3 100644
--- a/railties/lib/rails/generators/model_helpers.rb
+++ b/railties/lib/rails/generators/model_helpers.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rails/generators/active_model"
module Rails
diff --git a/railties/lib/rails/generators/named_base.rb b/railties/lib/rails/generators/named_base.rb
index aef66adb64..99165168fd 100644
--- a/railties/lib/rails/generators/named_base.rb
+++ b/railties/lib/rails/generators/named_base.rb
@@ -1,4 +1,5 @@
-require "active_support/core_ext/module/introspection"
+# frozen_string_literal: true
+
require "rails/generators/base"
require "rails/generators/generated_attribute"
@@ -6,8 +7,6 @@ module Rails
module Generators
class NamedBase < Base
argument :name, type: :string
- class_option :skip_namespace, type: :boolean, default: false,
- desc: "Skip namespace (affects only isolated applications)"
def initialize(args, *options) #:nodoc:
@inside_template = nil
@@ -45,24 +44,6 @@ module Rails
file_name
end
- # Wrap block with namespace of current application
- # if namespace exists and is not skipped
- def module_namespacing(&block) # :doc:
- content = capture(&block)
- content = wrap_with_namespace(content) if namespaced?
- concat(content)
- end
-
- def indent(content, multiplier = 2) # :doc:
- spaces = " " * multiplier
- content.each_line.map { |line| line.blank? ? line : "#{spaces}#{line}" }.join
- end
-
- def wrap_with_namespace(content) # :doc:
- content = indent(content).chomp
- "module #{namespace.name}\n#{content}\nend\n"
- end
-
def inside_template # :doc:
@inside_template = true
yield
@@ -74,18 +55,6 @@ module Rails
@inside_template
end
- def namespace # :doc:
- Rails::Generators.namespace
- end
-
- def namespaced? # :doc:
- !options[:skip_namespace] && namespace
- end
-
- def namespace_dirs
- @namespace_dirs ||= namespace.name.split("::").map(&:underscore)
- end
-
def file_path # :doc:
@file_path ||= (class_path + [file_name]).join("/")
end
@@ -102,10 +71,6 @@ module Rails
@namespaced_class_path ||= namespace_dirs + @class_path
end
- def namespaced_path # :doc:
- @namespaced_path ||= namespace_dirs.join("/")
- end
-
def class_name # :doc:
(class_path + [file_name]).map!(&:camelize).join("::")
end
@@ -134,11 +99,11 @@ module Rails
end
def index_helper # :doc:
- uncountable? ? "#{plural_table_name}_index" : plural_table_name
+ uncountable? ? "#{plural_route_name}_index" : plural_route_name
end
def show_helper # :doc:
- "#{singular_table_name}_url(@#{singular_table_name})"
+ "#{singular_route_name}_url(@#{singular_table_name})"
end
def edit_helper # :doc:
@@ -146,7 +111,7 @@ module Rails
end
def new_helper # :doc:
- "new_#{singular_table_name}_url"
+ "new_#{singular_route_name}_url"
end
def field_id(attribute_name)
@@ -186,6 +151,35 @@ module Rails
end
end
+ def redirect_resource_name # :doc:
+ model_resource_name(prefix: "@")
+ end
+
+ def model_resource_name(prefix: "") # :doc:
+ resource_name = "#{prefix}#{singular_table_name}"
+ if options[:model_name]
+ "[#{controller_class_path.map { |name| ":" + name }.join(", ")}, #{resource_name}]"
+ else
+ resource_name
+ end
+ end
+
+ def singular_route_name # :doc:
+ if options[:model_name]
+ "#{controller_class_path.join('_')}_#{singular_table_name}"
+ else
+ singular_table_name
+ end
+ end
+
+ def plural_route_name # :doc:
+ if options[:model_name]
+ "#{controller_class_path.join('_')}_#{plural_table_name}"
+ else
+ plural_table_name
+ end
+ end
+
def assign_names!(name)
@class_path = name.include?("/") ? name.split("/") : name.split("::")
@class_path.map!(&:underscore)
@@ -227,7 +221,7 @@ module Rails
#
def self.check_class_collision(options = {}) # :doc:
define_method :check_class_collision do
- name = if respond_to?(:controller_class_name) # for ScaffoldBase
+ name = if respond_to?(:controller_class_name) # for ResourceHelpers
controller_class_name
else
class_name
diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb
index 45b9e7bdff..1fdfc3ca52 100644
--- a/railties/lib/rails/generators/rails/app/app_generator.rb
+++ b/railties/lib/rails/generators/rails/app/app_generator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rails/generators/app_base"
module Rails
@@ -49,6 +51,10 @@ module Rails
copy_file "README.md", "README.md"
end
+ def ruby_version
+ template "ruby-version", ".ruby-version"
+ end
+
def gemfile
template "Gemfile"
end
@@ -63,7 +69,7 @@ module Rails
def version_control
if !options[:skip_git] && !options[:pretend]
- run "git init"
+ run "git init", capture: options[:quiet]
end
end
@@ -105,10 +111,10 @@ module Rails
template "routes.rb"
template "application.rb"
template "environment.rb"
- template "secrets.yml"
template "cable.yml" unless options[:skip_action_cable]
template "puma.rb" unless options[:skip_puma]
template "spring.rb" if spring_install?
+ template "storage.yml" unless skip_active_storage?
directory "environments"
directory "initializers"
@@ -118,9 +124,10 @@ module Rails
def config_when_updating
cookie_serializer_config_exist = File.exist?("config/initializers/cookies_serializer.rb")
- action_cable_config_exist = File.exist?("config/cable.yml")
- rack_cors_config_exist = File.exist?("config/initializers/cors.rb")
- assets_config_exist = File.exist?("config/initializers/assets.rb")
+ action_cable_config_exist = File.exist?("config/cable.yml")
+ active_storage_config_exist = File.exist?("config/storage.yml")
+ rack_cors_config_exist = File.exist?("config/initializers/cors.rb")
+ assets_config_exist = File.exist?("config/initializers/assets.rb")
config
@@ -128,10 +135,14 @@ module Rails
gsub_file "config/initializers/cookies_serializer.rb", /json(?!,)/, "marshal"
end
- unless action_cable_config_exist
+ if !options[:skip_action_cable] && !action_cable_config_exist
template "config/cable.yml"
end
+ if !skip_active_storage? && !active_storage_config_exist
+ template "config/storage.yml"
+ end
+
unless rack_cors_config_exist
remove_file "config/initializers/cors.rb"
end
@@ -147,6 +158,22 @@ module Rails
end
end
+ def master_key
+ return if options[:pretend] || options[:dummy_app]
+
+ require "rails/generators/rails/master_key/master_key_generator"
+ master_key_generator = Rails::Generators::MasterKeyGenerator.new([], quiet: options[:quiet])
+ master_key_generator.add_master_key_file_silently
+ master_key_generator.ignore_master_key_file_silently
+ end
+
+ def credentials
+ return if options[:pretend] || options[:dummy_app]
+
+ require "rails/generators/rails/credentials/credentials_generator"
+ Rails::Generators::CredentialsGenerator.new([], quiet: options[:quiet]).add_credentials_file_silently
+ end
+
def database_yml
template "config/databases/#{options[:database]}.yml", "config/database.yml"
end
@@ -169,6 +196,11 @@ module Rails
directory "public", "public", recursive: false
end
+ def storage
+ empty_directory_with_keep_file "storage"
+ empty_directory_with_keep_file "tmp/storage"
+ end
+
def test
empty_directory_with_keep_file "test/fixtures"
empty_directory_with_keep_file "test/fixtures/files"
@@ -242,6 +274,7 @@ module Rails
def create_root_files
build(:readme)
build(:rakefile)
+ build(:ruby_version)
build(:configru)
build(:gitignore) unless options[:skip_git]
build(:gemfile) unless options[:skip_gemfile]
@@ -271,6 +304,14 @@ module Rails
end
remove_task :update_config_files
+ def create_master_key
+ build(:master_key)
+ end
+
+ def create_credentials
+ build(:credentials)
+ end
+
def display_upgrade_guide_info
say "\nAfter this, check Rails upgrade guide at http://guides.rubyonrails.org/upgrading_ruby_on_rails.html for more details about upgrading your app."
end
@@ -310,6 +351,10 @@ module Rails
build(:system_test) if depends_on_system_test?
end
+ def create_storage_files
+ build(:storage) unless skip_active_storage?
+ end
+
def create_tmp_files
build(:tmp)
end
@@ -379,7 +424,6 @@ module Rails
def delete_action_cable_files_skipping_action_cable
if options[:skip_action_cable]
- remove_file "config/cable.yml"
remove_file "app/assets/javascripts/cable.js"
remove_dir "app/channels"
end
@@ -413,6 +457,7 @@ module Rails
public_task :apply_rails_template, :run_bundle
public_task :run_webpack, :generate_spring_binstubs
+ public_task :run_active_storage
def run_after_bundle_callbacks
@after_bundle_callbacks.each(&:call)
@@ -465,10 +510,6 @@ module Rails
end
end
- def app_secret
- SecureRandom.hex(64)
- end
-
def mysql_socket
@mysql_socket ||= [
"/tmp/mysql.sock", # default
diff --git a/railties/lib/rails/generators/rails/app/templates/Gemfile b/railties/lib/rails/generators/rails/app/templates/Gemfile.tt
index 747d2e6253..61026f5182 100644
--- a/railties/lib/rails/generators/rails/app/templates/Gemfile
+++ b/railties/lib/rails/generators/rails/app/templates/Gemfile.tt
@@ -1,6 +1,11 @@
source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
+ruby <%= "'#{RUBY_VERSION}'" -%>
+
+<% unless gemfile_entries.first.comment -%>
+
+<% end -%>
<% gemfile_entries.each do |gem| -%>
<% if gem.comment -%>
@@ -15,10 +20,18 @@ git_source(:github) { |repo| "https://github.com/#{repo}.git" }
# Use ActiveModel has_secure_password
# gem 'bcrypt', '~> 3.1.7'
+<% unless skip_active_storage? -%>
+
+# Use ActiveStorage variant
+# gem 'mini_magick', '~> 4.8'
+<% end -%>
# Use Capistrano for deployment
# gem 'capistrano-rails', group: :development
+# Reduces boot times through caching; required in config/boot.rb
+gem 'bootsnap', '>= 1.1.0', require: false
+
<%- if options.api? -%>
# Use Rack CORS for handling Cross-Origin Resource Sharing (CORS), making cross-origin AJAX possible
# gem 'rack-cors'
@@ -30,14 +43,16 @@ group :development, :test do
gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
<%- if depends_on_system_test? -%>
# Adds support for Capybara system testing and selenium driver
- gem 'capybara', '~> 2.13'
+ gem 'capybara', '~> 2.15'
gem 'selenium-webdriver'
+ # Easy installation and use of chromedriver to run system tests with Chrome
+ gem 'chromedriver-helper'
<%- end -%>
end
group :development do
<%- unless options.api? -%>
- # Access an IRB console on exception pages or by using <%%= console %> anywhere in the code.
+ # Access an interactive console on exception pages or by calling 'console' anywhere in the code.
<%- if options.dev? || options.edge? -%>
gem 'web-console', github: 'rails/web-console'
<%- else -%>
diff --git a/railties/lib/rails/generators/rails/app/templates/README.md b/railties/lib/rails/generators/rails/app/templates/README.md.tt
index 7db80e4ca1..7db80e4ca1 100644
--- a/railties/lib/rails/generators/rails/app/templates/README.md
+++ b/railties/lib/rails/generators/rails/app/templates/README.md.tt
diff --git a/railties/lib/rails/generators/rails/app/templates/Rakefile b/railties/lib/rails/generators/rails/app/templates/Rakefile.tt
index e85f913914..e85f913914 100644
--- a/railties/lib/rails/generators/rails/app/templates/Rakefile
+++ b/railties/lib/rails/generators/rails/app/templates/Rakefile.tt
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
index 4206002a1b..5183bcd256 100644
--- 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
@@ -12,6 +12,9 @@
//
<% unless options[:skip_javascript] -%>
//= require rails-ujs
+<% unless skip_active_storage? -%>
+//= require activestorage
+<% end -%>
<% unless options[:skip_turbolinks] -%>
//= require turbolinks
<% end -%>
diff --git a/railties/lib/rails/generators/rails/app/templates/app/assets/javascripts/cable.js b/railties/lib/rails/generators/rails/app/templates/app/assets/javascripts/cable.js.tt
index 739aa5f022..739aa5f022 100644
--- a/railties/lib/rails/generators/rails/app/templates/app/assets/javascripts/cable.js
+++ b/railties/lib/rails/generators/rails/app/templates/app/assets/javascripts/cable.js.tt
diff --git a/railties/lib/rails/generators/rails/app/templates/app/assets/stylesheets/application.css b/railties/lib/rails/generators/rails/app/templates/app/assets/stylesheets/application.css.tt
index d05ea0f511..d05ea0f511 100644
--- a/railties/lib/rails/generators/rails/app/templates/app/assets/stylesheets/application.css
+++ b/railties/lib/rails/generators/rails/app/templates/app/assets/stylesheets/application.css.tt
diff --git a/railties/lib/rails/generators/rails/app/templates/app/channels/application_cable/channel.rb b/railties/lib/rails/generators/rails/app/templates/app/channels/application_cable/channel.rb.tt
index d672697283..d672697283 100644
--- a/railties/lib/rails/generators/rails/app/templates/app/channels/application_cable/channel.rb
+++ b/railties/lib/rails/generators/rails/app/templates/app/channels/application_cable/channel.rb.tt
diff --git a/railties/lib/rails/generators/rails/app/templates/app/channels/application_cable/connection.rb b/railties/lib/rails/generators/rails/app/templates/app/channels/application_cable/connection.rb.tt
index 0ff5442f47..0ff5442f47 100644
--- a/railties/lib/rails/generators/rails/app/templates/app/channels/application_cable/connection.rb
+++ b/railties/lib/rails/generators/rails/app/templates/app/channels/application_cable/connection.rb.tt
diff --git a/railties/lib/rails/generators/rails/app/templates/app/controllers/application_controller.rb.tt b/railties/lib/rails/generators/rails/app/templates/app/controllers/application_controller.rb.tt
index 413354186d..938eff8ed0 100644
--- a/railties/lib/rails/generators/rails/app/templates/app/controllers/application_controller.rb.tt
+++ b/railties/lib/rails/generators/rails/app/templates/app/controllers/application_controller.rb.tt
@@ -1,5 +1,2 @@
-class ApplicationController < ActionController::<%= options[:api] ? "API" : "Base" %>
-<%- unless options[:api] -%>
- protect_from_forgery with: :exception
-<%- end -%>
+class ApplicationController < ActionController::<%= options.api? ? "API" : "Base" %>
end
diff --git a/railties/lib/rails/generators/rails/app/templates/app/helpers/application_helper.rb b/railties/lib/rails/generators/rails/app/templates/app/helpers/application_helper.rb.tt
index de6be7945c..de6be7945c 100644
--- a/railties/lib/rails/generators/rails/app/templates/app/helpers/application_helper.rb
+++ b/railties/lib/rails/generators/rails/app/templates/app/helpers/application_helper.rb.tt
diff --git a/railties/lib/rails/generators/rails/app/templates/app/jobs/application_job.rb b/railties/lib/rails/generators/rails/app/templates/app/jobs/application_job.rb.tt
index a009ace51c..a009ace51c 100644
--- a/railties/lib/rails/generators/rails/app/templates/app/jobs/application_job.rb
+++ b/railties/lib/rails/generators/rails/app/templates/app/jobs/application_job.rb.tt
diff --git a/railties/lib/rails/generators/rails/app/templates/app/mailers/application_mailer.rb b/railties/lib/rails/generators/rails/app/templates/app/mailers/application_mailer.rb.tt
index 286b2239d1..286b2239d1 100644
--- a/railties/lib/rails/generators/rails/app/templates/app/mailers/application_mailer.rb
+++ b/railties/lib/rails/generators/rails/app/templates/app/mailers/application_mailer.rb.tt
diff --git a/railties/lib/rails/generators/rails/app/templates/app/models/application_record.rb b/railties/lib/rails/generators/rails/app/templates/app/models/application_record.rb.tt
index 10a4cba84d..10a4cba84d 100644
--- a/railties/lib/rails/generators/rails/app/templates/app/models/application_record.rb
+++ b/railties/lib/rails/generators/rails/app/templates/app/models/application_record.rb.tt
diff --git a/railties/lib/rails/generators/rails/app/templates/bin/bundle b/railties/lib/rails/generators/rails/app/templates/bin/bundle.tt
index a84f0afe47..a84f0afe47 100644
--- a/railties/lib/rails/generators/rails/app/templates/bin/bundle
+++ b/railties/lib/rails/generators/rails/app/templates/bin/bundle.tt
diff --git a/railties/lib/rails/generators/rails/app/templates/bin/rails b/railties/lib/rails/generators/rails/app/templates/bin/rails.tt
index 513a2e0183..513a2e0183 100644
--- a/railties/lib/rails/generators/rails/app/templates/bin/rails
+++ b/railties/lib/rails/generators/rails/app/templates/bin/rails.tt
diff --git a/railties/lib/rails/generators/rails/app/templates/bin/rake b/railties/lib/rails/generators/rails/app/templates/bin/rake.tt
index d14fc8395b..d14fc8395b 100644
--- a/railties/lib/rails/generators/rails/app/templates/bin/rake
+++ b/railties/lib/rails/generators/rails/app/templates/bin/rake.tt
diff --git a/railties/lib/rails/generators/rails/app/templates/bin/setup.tt b/railties/lib/rails/generators/rails/app/templates/bin/setup.tt
index ee9d077c30..233b5a1d95 100644
--- a/railties/lib/rails/generators/rails/app/templates/bin/setup.tt
+++ b/railties/lib/rails/generators/rails/app/templates/bin/setup.tt
@@ -15,11 +15,12 @@ chdir APP_ROOT do
puts '== Installing dependencies =='
system! 'gem install bundler --conservative'
system('bundle check') || system!('bundle install')
-<% unless options[:skip_yarn] %>
+<% unless options.skip_yarn? -%>
+
# Install JavaScript dependencies if using Yarn
# system('bin/yarn')
-<% end %>
-<% unless options.skip_active_record -%>
+<% end -%>
+<% unless options.skip_active_record? -%>
# puts "\n== Copying sample files =="
# unless File.exist?('config/database.yml')
diff --git a/railties/lib/rails/generators/rails/app/templates/bin/update.tt b/railties/lib/rails/generators/rails/app/templates/bin/update.tt
index 5b6e50883e..70cc71d83b 100644
--- a/railties/lib/rails/generators/rails/app/templates/bin/update.tt
+++ b/railties/lib/rails/generators/rails/app/templates/bin/update.tt
@@ -15,7 +15,12 @@ chdir APP_ROOT do
puts '== Installing dependencies =='
system! 'gem install bundler --conservative'
system('bundle check') || system!('bundle install')
-<% unless options.skip_active_record -%>
+<% unless options.skip_yarn? -%>
+
+ # Install JavaScript dependencies if using Yarn
+ # system('bin/yarn')
+<% end -%>
+<% unless options.skip_active_record? -%>
puts "\n== Updating database =="
system! 'bin/rails db:migrate'
diff --git a/railties/lib/rails/generators/rails/app/templates/bin/yarn b/railties/lib/rails/generators/rails/app/templates/bin/yarn.tt
index 44f75c22a4..b4e4d95286 100644
--- a/railties/lib/rails/generators/rails/app/templates/bin/yarn
+++ b/railties/lib/rails/generators/rails/app/templates/bin/yarn.tt
@@ -1,7 +1,7 @@
-VENDOR_PATH = File.expand_path('..', __dir__)
-Dir.chdir(VENDOR_PATH) do
+APP_ROOT = File.expand_path('..', __dir__)
+Dir.chdir(APP_ROOT) do
begin
- exec "yarnpkg #{ARGV.join(" ")}"
+ exec "yarnpkg #{ARGV.join(' ')}"
rescue Errno::ENOENT
$stderr.puts "Yarn executable was not detected in the system."
$stderr.puts "Download Yarn at https://yarnpkg.com/en/docs/install"
diff --git a/railties/lib/rails/generators/rails/app/templates/config.ru b/railties/lib/rails/generators/rails/app/templates/config.ru.tt
index f7ba0b527b..f7ba0b527b 100644
--- a/railties/lib/rails/generators/rails/app/templates/config.ru
+++ b/railties/lib/rails/generators/rails/app/templates/config.ru.tt
diff --git a/railties/lib/rails/generators/rails/app/templates/config/application.rb b/railties/lib/rails/generators/rails/app/templates/config/application.rb.tt
index 0b1d22228e..9e03e86771 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/application.rb
+++ b/railties/lib/rails/generators/rails/app/templates/config/application.rb.tt
@@ -8,6 +8,7 @@ require "rails"
require "active_model/railtie"
require "active_job/railtie"
<%= comment_if :skip_active_record %>require "active_record/railtie"
+<%= comment_if :skip_active_storage %>require "active_storage/engine"
require "action_controller/railtie"
<%= comment_if :skip_action_mailer %>require "action_mailer/railtie"
require "action_view/railtie"
@@ -28,7 +29,7 @@ module <%= app_const_base %>
# Settings in config/environments/* take precedence over those specified here.
# Application configuration should go into files in config/initializers
# -- all .rb files in that directory are automatically loaded.
-<%- if options[:api] -%>
+<%- if options.api? -%>
# Only loads a smaller set of middleware suitable for API only apps.
# Middleware like session, flash, cookies can be added back manually.
diff --git a/railties/lib/rails/generators/rails/app/templates/config/boot.rb b/railties/lib/rails/generators/rails/app/templates/config/boot.rb.tt
index 30f5120df6..b9e460cef3 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/boot.rb
+++ b/railties/lib/rails/generators/rails/app/templates/config/boot.rb.tt
@@ -1,3 +1,4 @@
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
require 'bundler/setup' # Set up gems listed in the Gemfile.
+require 'bootsnap/setup' # Speed up boot time by caching expensive operations.
diff --git a/railties/lib/rails/generators/rails/app/templates/config/cable.yml b/railties/lib/rails/generators/rails/app/templates/config/cable.yml.tt
index 1da4913082..8e53156c71 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/cable.yml
+++ b/railties/lib/rails/generators/rails/app/templates/config/cable.yml.tt
@@ -6,5 +6,5 @@ test:
production:
adapter: redis
- url: redis://localhost:6379/1
+ url: <%%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %>
channel_prefix: <%= app_name %>_production
diff --git a/railties/lib/rails/generators/rails/app/templates/config/databases/frontbase.yml b/railties/lib/rails/generators/rails/app/templates/config/databases/frontbase.yml.tt
index 917b52e535..917b52e535 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/databases/frontbase.yml
+++ b/railties/lib/rails/generators/rails/app/templates/config/databases/frontbase.yml.tt
diff --git a/railties/lib/rails/generators/rails/app/templates/config/databases/ibm_db.yml b/railties/lib/rails/generators/rails/app/templates/config/databases/ibm_db.yml.tt
index d40117a27f..d40117a27f 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/databases/ibm_db.yml
+++ b/railties/lib/rails/generators/rails/app/templates/config/databases/ibm_db.yml.tt
diff --git a/railties/lib/rails/generators/rails/app/templates/config/databases/jdbc.yml b/railties/lib/rails/generators/rails/app/templates/config/databases/jdbc.yml.tt
index 563be77710..563be77710 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/databases/jdbc.yml
+++ b/railties/lib/rails/generators/rails/app/templates/config/databases/jdbc.yml.tt
diff --git a/railties/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml b/railties/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml.tt
index 8bc8735a8e..2a67bdca25 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml
+++ b/railties/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml.tt
@@ -7,7 +7,7 @@
# gem 'activerecord-jdbcmysql-adapter'
#
# And be sure to use new-style password hashing:
-# http://dev.mysql.com/doc/refman/5.7/en/old-client.html
+# https://dev.mysql.com/doc/refman/5.7/en/password-hashing.html
#
default: &default
adapter: mysql
diff --git a/railties/lib/rails/generators/rails/app/templates/config/databases/jdbcpostgresql.yml b/railties/lib/rails/generators/rails/app/templates/config/databases/jdbcpostgresql.yml.tt
index 70df04079d..70df04079d 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/databases/jdbcpostgresql.yml
+++ b/railties/lib/rails/generators/rails/app/templates/config/databases/jdbcpostgresql.yml.tt
diff --git a/railties/lib/rails/generators/rails/app/templates/config/databases/jdbcsqlite3.yml b/railties/lib/rails/generators/rails/app/templates/config/databases/jdbcsqlite3.yml.tt
index 371415e6a8..371415e6a8 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/databases/jdbcsqlite3.yml
+++ b/railties/lib/rails/generators/rails/app/templates/config/databases/jdbcsqlite3.yml.tt
diff --git a/railties/lib/rails/generators/rails/app/templates/config/databases/mysql.yml b/railties/lib/rails/generators/rails/app/templates/config/databases/mysql.yml.tt
index 269af1470d..04afaa0596 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/databases/mysql.yml
+++ b/railties/lib/rails/generators/rails/app/templates/config/databases/mysql.yml.tt
@@ -7,7 +7,7 @@
# gem 'mysql2'
#
# And be sure to use new-style password hashing:
-# http://dev.mysql.com/doc/refman/5.7/en/old-client.html
+# https://dev.mysql.com/doc/refman/5.7/en/password-hashing.html
#
default: &default
adapter: mysql2
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.tt
index 6da0601b24..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.tt
diff --git a/railties/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml b/railties/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml.tt
index 145cfb7f74..145cfb7f74 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml
+++ b/railties/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml.tt
diff --git a/railties/lib/rails/generators/rails/app/templates/config/databases/sqlite3.yml b/railties/lib/rails/generators/rails/app/templates/config/databases/sqlite3.yml.tt
index 9510568124..9510568124 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/databases/sqlite3.yml
+++ b/railties/lib/rails/generators/rails/app/templates/config/databases/sqlite3.yml.tt
diff --git a/railties/lib/rails/generators/rails/app/templates/config/databases/sqlserver.yml b/railties/lib/rails/generators/rails/app/templates/config/databases/sqlserver.yml.tt
index a21555e573..049de65f22 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/databases/sqlserver.yml
+++ b/railties/lib/rails/generators/rails/app/templates/config/databases/sqlserver.yml.tt
@@ -1,4 +1,4 @@
-# SQL Server (2012 or higher recommended)
+# SQL Server (2012 or higher required)
#
# Install the adapters and driver
# gem install tiny_tds
@@ -12,7 +12,7 @@ default: &default
adapter: sqlserver
encoding: utf8
username: sa
- password: <%= ENV['SA_PASSWORD'] %>
+ password: <%%= ENV['SA_PASSWORD'] %>
host: localhost
development:
diff --git a/railties/lib/rails/generators/rails/app/templates/config/environment.rb b/railties/lib/rails/generators/rails/app/templates/config/environment.rb.tt
index 426333bb46..426333bb46 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/environment.rb
+++ b/railties/lib/rails/generators/rails/app/templates/config/environment.rb.tt
diff --git a/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt
index b75b65c8df..b383228dc0 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt
+++ b/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt
@@ -19,13 +19,18 @@ Rails.application.configure do
config.cache_store = :memory_store
config.public_file_server.headers = {
- 'Cache-Control' => "public, max-age=#{2.days.seconds.to_i}"
+ 'Cache-Control' => "public, max-age=#{2.days.to_i}"
}
else
config.action_controller.perform_caching = false
config.cache_store = :null_store
end
+ <%- unless skip_active_storage? -%>
+
+ # Store uploaded files on the local file system (see config/storage.yml for options)
+ config.active_storage.service = :local
+ <%- end -%>
<%- unless options.skip_action_mailer? -%>
# Don't care if the mailer can't send.
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 d44331a888..4c0f36db98 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
@@ -14,10 +14,9 @@ Rails.application.configure do
config.consider_all_requests_local = false
config.action_controller.perform_caching = true
- # Attempt to read encrypted secrets from `config/secrets.yml.enc`.
- # Requires an encryption key in `ENV["RAILS_MASTER_KEY"]` or
- # `config/secrets.yml.key`.
- config.read_encrypted_secrets = true
+ # Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"]
+ # or in config/master.key. This key is used to decrypt credentials (and other encrypted files).
+ # config.require_master_key = true
# Disable serving static files from the `/public` folder by default since
# Apache or NGINX already handles this.
@@ -45,6 +44,11 @@ Rails.application.configure do
# config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache
# config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX
+ <%- unless skip_active_storage? -%>
+ # Store uploaded files on the local file system (see config/storage.yml for options)
+ config.active_storage.service = :local
+
+ <%- end -%>
<%- unless options[:skip_action_cable] -%>
# Mount Action Cable outside main process or domain
# config.action_cable.mount_path = nil
diff --git a/railties/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt
index 56416b3075..ff4c89219a 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt
+++ b/railties/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt
@@ -15,7 +15,7 @@ Rails.application.configure do
# Configure public file server for tests with Cache-Control for performance.
config.public_file_server.enabled = true
config.public_file_server.headers = {
- 'Cache-Control' => "public, max-age=#{1.hour.seconds.to_i}"
+ 'Cache-Control' => "public, max-age=#{1.hour.to_i}"
}
# Show full error reports and disable caching.
@@ -27,6 +27,12 @@ Rails.application.configure do
# Disable request forgery protection in test environment.
config.action_controller.allow_forgery_protection = false
+
+ <%- unless skip_active_storage? -%>
+ # Store uploaded files on the local file system in a temporary directory
+ config.active_storage.service = :test
+
+ <%- end -%>
<%- unless options.skip_action_mailer? -%>
config.action_mailer.perform_caching = false
@@ -34,8 +40,8 @@ Rails.application.configure do
# The :test delivery method accumulates sent emails in the
# ActionMailer::Base.deliveries array.
config.action_mailer.delivery_method = :test
- <%- end -%>
+ <%- end -%>
# Print deprecation notices to the stderr.
config.active_support.deprecation = :stderr
diff --git a/railties/lib/rails/generators/rails/app/templates/config/initializers/application_controller_renderer.rb b/railties/lib/rails/generators/rails/app/templates/config/initializers/application_controller_renderer.rb
deleted file mode 100644
index 51639b67a0..0000000000
--- a/railties/lib/rails/generators/rails/app/templates/config/initializers/application_controller_renderer.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-# Be sure to restart your server when you modify this file.
-
-# ApplicationController.renderer.defaults.merge!(
-# http_host: 'example.org',
-# https: false
-# )
diff --git a/railties/lib/rails/generators/rails/app/templates/config/initializers/application_controller_renderer.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/initializers/application_controller_renderer.rb.tt
new file mode 100644
index 0000000000..89d2efab2b
--- /dev/null
+++ b/railties/lib/rails/generators/rails/app/templates/config/initializers/application_controller_renderer.rb.tt
@@ -0,0 +1,8 @@
+# Be sure to restart your server when you modify this file.
+
+# ActiveSupport::Reloader.to_prepare do
+# ApplicationController.renderer.defaults.merge!(
+# http_host: 'example.org',
+# https: false
+# )
+# end
diff --git a/railties/lib/rails/generators/rails/app/templates/config/initializers/backtrace_silencers.rb b/railties/lib/rails/generators/rails/app/templates/config/initializers/backtrace_silencers.rb.tt
index 59385cdf37..59385cdf37 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/initializers/backtrace_silencers.rb
+++ b/railties/lib/rails/generators/rails/app/templates/config/initializers/backtrace_silencers.rb.tt
diff --git a/railties/lib/rails/generators/rails/app/templates/config/initializers/cookies_serializer.rb b/railties/lib/rails/generators/rails/app/templates/config/initializers/cookies_serializer.rb.tt
index 5a6a32d371..5a6a32d371 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/initializers/cookies_serializer.rb
+++ b/railties/lib/rails/generators/rails/app/templates/config/initializers/cookies_serializer.rb.tt
diff --git a/railties/lib/rails/generators/rails/app/templates/config/initializers/cors.rb b/railties/lib/rails/generators/rails/app/templates/config/initializers/cors.rb.tt
index 3b1c1b5ed1..3b1c1b5ed1 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/initializers/cors.rb
+++ b/railties/lib/rails/generators/rails/app/templates/config/initializers/cors.rb.tt
diff --git a/railties/lib/rails/generators/rails/app/templates/config/initializers/filter_parameter_logging.rb b/railties/lib/rails/generators/rails/app/templates/config/initializers/filter_parameter_logging.rb.tt
index 4a994e1e7b..4a994e1e7b 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/initializers/filter_parameter_logging.rb
+++ b/railties/lib/rails/generators/rails/app/templates/config/initializers/filter_parameter_logging.rb.tt
diff --git a/railties/lib/rails/generators/rails/app/templates/config/initializers/inflections.rb b/railties/lib/rails/generators/rails/app/templates/config/initializers/inflections.rb.tt
index ac033bf9dc..ac033bf9dc 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/initializers/inflections.rb
+++ b/railties/lib/rails/generators/rails/app/templates/config/initializers/inflections.rb.tt
diff --git a/railties/lib/rails/generators/rails/app/templates/config/initializers/mime_types.rb b/railties/lib/rails/generators/rails/app/templates/config/initializers/mime_types.rb.tt
index dc1899682b..dc1899682b 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/initializers/mime_types.rb
+++ b/railties/lib/rails/generators/rails/app/templates/config/initializers/mime_types.rb.tt
diff --git a/railties/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_5_2.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_5_2.rb.tt
index 900baa607a..25dcddb27a 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_5_2.rb.tt
+++ b/railties/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_5_2.rb.tt
@@ -13,3 +13,15 @@
# Use AES 256 GCM authenticated encryption for encrypted cookies.
# Existing cookies will be converted on read then written with the new scheme.
# Rails.application.config.action_dispatch.use_authenticated_cookie_encryption = true
+
+# Use AES-256-GCM authenticated encryption as default cipher for encrypting messages
+# instead of AES-256-CBC, when use_authenticated_message_encryption is set to true.
+# Rails.application.config.active_support.use_authenticated_message_encryption = true
+
+# Add default protection from forgery to ActionController::Base instead of in
+# ApplicationController.
+# Rails.application.config.action_controller.default_protect_from_forgery = true
+
+# Store boolean values are in sqlite3 databases as 1 and 0 instead of 't' and
+# 'f' after migrating old data.
+# Rails.application.config.active_record.sqlite3.represent_boolean_as_integer = true
diff --git a/railties/lib/rails/generators/rails/app/templates/config/puma.rb b/railties/lib/rails/generators/rails/app/templates/config/puma.rb.tt
index 1e19380dcb..1e19380dcb 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/puma.rb
+++ b/railties/lib/rails/generators/rails/app/templates/config/puma.rb.tt
diff --git a/railties/lib/rails/generators/rails/app/templates/config/routes.rb b/railties/lib/rails/generators/rails/app/templates/config/routes.rb.tt
index 787824f888..787824f888 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/routes.rb
+++ b/railties/lib/rails/generators/rails/app/templates/config/routes.rb.tt
diff --git a/railties/lib/rails/generators/rails/app/templates/config/secrets.yml b/railties/lib/rails/generators/rails/app/templates/config/secrets.yml
deleted file mode 100644
index ea9d47396c..0000000000
--- a/railties/lib/rails/generators/rails/app/templates/config/secrets.yml
+++ /dev/null
@@ -1,32 +0,0 @@
-# Be sure to restart your server when you modify this file.
-
-# Your secret key is used for verifying the integrity of signed cookies.
-# If you change this key, all old signed cookies will become invalid!
-
-# Make sure the secret is at least 30 characters and all random,
-# no regular words or you'll be exposed to dictionary attacks.
-# You can use `rails secret` to generate a secure secret key.
-
-# Make sure the secrets in this file are kept private
-# if you're sharing your code publicly.
-
-# Shared secrets are available across all environments.
-
-# shared:
-# api_key: a1B2c3D4e5F6
-
-# Environmental secrets are only available for that specific environment.
-
-development:
- secret_key_base: <%= app_secret %>
-
-test:
- secret_key_base: <%= app_secret %>
-
-# Do not keep production secrets in the unencrypted secrets file.
-# Instead, either read values from the environment.
-# Or, use `bin/rails secrets:setup` to configure encrypted secrets
-# and move the `production:` environment over there.
-
-production:
- secret_key_base: <%%= ENV["SECRET_KEY_BASE"] %>
diff --git a/railties/lib/rails/generators/rails/app/templates/config/spring.rb b/railties/lib/rails/generators/rails/app/templates/config/spring.rb.tt
index c9119b40c0..9fa7863f99 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/spring.rb
+++ b/railties/lib/rails/generators/rails/app/templates/config/spring.rb.tt
@@ -1,6 +1,6 @@
-%w(
+%w[
.ruby-version
.rbenv-vars
tmp/restart.txt
tmp/caching-dev.txt
-).each { |path| Spring.watch(path) }
+].each { |path| Spring.watch(path) }
diff --git a/railties/lib/rails/generators/rails/app/templates/config/storage.yml.tt b/railties/lib/rails/generators/rails/app/templates/config/storage.yml.tt
new file mode 100644
index 0000000000..9bada4b66d
--- /dev/null
+++ b/railties/lib/rails/generators/rails/app/templates/config/storage.yml.tt
@@ -0,0 +1,35 @@
+test:
+ service: Disk
+ root: <%%= Rails.root.join("tmp/storage") %>
+
+local:
+ service: Disk
+ root: <%%= Rails.root.join("storage") %>
+
+# Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key)
+# amazon:
+# service: S3
+# access_key_id: <%%= Rails.application.credentials.dig(:aws, :access_key_id) %>
+# secret_access_key: <%%= Rails.application.credentials.dig(:aws, :secret_access_key) %>
+# region: us-east-1
+# bucket: your_own_bucket
+
+# Remember not to checkin your GCS keyfile to a repository
+# google:
+# service: GCS
+# project: your_project
+# keyfile: <%%= Rails.root.join("path/to/gcs.keyfile") %>
+# bucket: your_own_bucket
+
+# Use rails credentials:edit to set the Azure Storage secret (as azure_storage:storage_access_key)
+# microsoft:
+# service: AzureStorage
+# path: your_azure_storage_path
+# storage_account_name: your_account_name
+# storage_access_key: <%%= Rails.application.credentials.dig(:azure_storage, :storage_access_key) %>
+# container: your_container_name
+
+# mirror:
+# service: Mirror
+# primary: local
+# mirrors: [ amazon, google, microsoft ]
diff --git a/railties/lib/rails/generators/rails/app/templates/gitignore b/railties/lib/rails/generators/rails/app/templates/gitignore.tt
index 7221c26729..2cd8335aba 100644
--- a/railties/lib/rails/generators/rails/app/templates/gitignore
+++ b/railties/lib/rails/generators/rails/app/templates/gitignore.tt
@@ -21,9 +21,17 @@
!/tmp/.keep
<% end -%>
-<% unless options[:skip_yarn] -%>
+<% unless skip_active_storage? -%>
+# Ignore uploaded files in development
+/storage/*
+
+<% end -%>
+<% unless options.skip_yarn? -%>
/node_modules
/yarn-error.log
<% end -%>
+<% unless options.api? -%>
+/public/assets
+<% end -%>
.byebug_history
diff --git a/railties/lib/rails/generators/rails/app/templates/package.json b/railties/lib/rails/generators/rails/app/templates/package.json.tt
index 46db57dcbe..46db57dcbe 100644
--- a/railties/lib/rails/generators/rails/app/templates/package.json
+++ b/railties/lib/rails/generators/rails/app/templates/package.json.tt
diff --git a/railties/lib/rails/generators/rails/app/templates/ruby-version.tt b/railties/lib/rails/generators/rails/app/templates/ruby-version.tt
new file mode 100644
index 0000000000..c444f33b0f
--- /dev/null
+++ b/railties/lib/rails/generators/rails/app/templates/ruby-version.tt
@@ -0,0 +1 @@
+<%= RUBY_VERSION -%>
diff --git a/railties/lib/rails/generators/rails/app/templates/test/application_system_test_case.rb b/railties/lib/rails/generators/rails/app/templates/test/application_system_test_case.rb.tt
index d19212abd5..d19212abd5 100644
--- a/railties/lib/rails/generators/rails/app/templates/test/application_system_test_case.rb
+++ b/railties/lib/rails/generators/rails/app/templates/test/application_system_test_case.rb.tt
diff --git a/railties/lib/rails/generators/rails/app/templates/test/test_helper.rb b/railties/lib/rails/generators/rails/app/templates/test/test_helper.rb.tt
index 7568af5b5e..6ad1f11781 100644
--- a/railties/lib/rails/generators/rails/app/templates/test/test_helper.rb
+++ b/railties/lib/rails/generators/rails/app/templates/test/test_helper.rb.tt
@@ -1,4 +1,4 @@
-require File.expand_path('../config/environment', __dir__)
+require_relative '../config/environment'
require 'rails/test_help'
class ActiveSupport::TestCase
diff --git a/railties/lib/rails/generators/rails/application_record/application_record_generator.rb b/railties/lib/rails/generators/rails/application_record/application_record_generator.rb
new file mode 100644
index 0000000000..f6b6e76b1d
--- /dev/null
+++ b/railties/lib/rails/generators/rails/application_record/application_record_generator.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+module Rails
+ module Generators
+ class ApplicationRecordGenerator < Base # :nodoc:
+ hook_for :orm, required: true, desc: "ORM to be invoked"
+ end
+ end
+end
diff --git a/railties/lib/rails/generators/rails/assets/assets_generator.rb b/railties/lib/rails/generators/rails/assets/assets_generator.rb
index 95d00c2d39..ffb695a1f3 100644
--- a/railties/lib/rails/generators/rails/assets/assets_generator.rb
+++ b/railties/lib/rails/generators/rails/assets/assets_generator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Rails
module Generators
class AssetsGenerator < NamedBase # :nodoc:
diff --git a/railties/lib/rails/generators/rails/assets/templates/stylesheet.css b/railties/lib/rails/generators/rails/assets/templates/stylesheet.css
index 7594abf268..afad32db02 100644
--- a/railties/lib/rails/generators/rails/assets/templates/stylesheet.css
+++ b/railties/lib/rails/generators/rails/assets/templates/stylesheet.css
@@ -1,4 +1,4 @@
-/*
+/*
Place all the styles related to the matching controller here.
They will automatically be included in application.css.
*/
diff --git a/railties/lib/rails/generators/rails/controller/controller_generator.rb b/railties/lib/rails/generators/rails/controller/controller_generator.rb
index 06bdb8b5ce..6d45d6e8f8 100644
--- a/railties/lib/rails/generators/rails/controller/controller_generator.rb
+++ b/railties/lib/rails/generators/rails/controller/controller_generator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Rails
module Generators
class ControllerGenerator < NamedBase # :nodoc:
@@ -13,12 +15,8 @@ module Rails
end
def add_routes
- unless options[:skip_routes]
- actions.reverse_each do |action|
- # route prepends two spaces onto the front of the string that is passed, this corrects that.
- route indent(generate_routing_code(action), 2)[2..-1]
- end
- end
+ return if options[:skip_routes]
+ route generate_routing_code
end
hook_for :template_engine, :test_framework, :helper, :assets
@@ -26,14 +24,15 @@ module Rails
private
# This method creates nested route entry for namespaced resources.
- # For eg. rails g controller foo/bar/baz index
+ # For eg. rails g controller foo/bar/baz index show
# Will generate -
# namespace :foo do
# namespace :bar do
# get 'baz/index'
+ # get 'baz/show'
# end
# end
- def generate_routing_code(action)
+ def generate_routing_code
depth = 0
lines = []
@@ -47,7 +46,10 @@ module Rails
# Create route
# get 'baz/index'
- lines << indent(%{get '#{file_name}/#{action}'\n}, depth * 2)
+ # get 'baz/show'
+ actions.each do |action|
+ lines << indent(%{get '#{file_name}/#{action}'\n}, depth * 2)
+ end
# Create `end` ladder
# end
diff --git a/railties/lib/rails/generators/rails/controller/templates/controller.rb b/railties/lib/rails/generators/rails/controller/templates/controller.rb.tt
index 633e0b3177..633e0b3177 100644
--- a/railties/lib/rails/generators/rails/controller/templates/controller.rb
+++ b/railties/lib/rails/generators/rails/controller/templates/controller.rb.tt
diff --git a/railties/lib/rails/generators/rails/credentials/credentials_generator.rb b/railties/lib/rails/generators/rails/credentials/credentials_generator.rb
new file mode 100644
index 0000000000..ab15da5423
--- /dev/null
+++ b/railties/lib/rails/generators/rails/credentials/credentials_generator.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+require "rails/generators/base"
+require "rails/generators/rails/master_key/master_key_generator"
+require "active_support/encrypted_configuration"
+
+module Rails
+ module Generators
+ class CredentialsGenerator < Base
+ def add_credentials_file
+ unless credentials.exist?
+ template = credentials_template
+
+ say "Adding #{credentials.content_path} to store encrypted credentials."
+ say ""
+ say "The following content has been encrypted with the Rails master key:"
+ say ""
+ say template, :on_green
+ say ""
+
+ add_credentials_file_silently(template)
+
+ say "You can edit encrypted credentials with `bin/rails credentials:edit`."
+ say ""
+ end
+ end
+
+ def add_credentials_file_silently(template = nil)
+ credentials.write(credentials_template)
+ end
+
+ private
+ def credentials
+ ActiveSupport::EncryptedConfiguration.new \
+ config_path: "config/credentials.yml.enc",
+ key_path: "config/master.key",
+ env_key: "RAILS_MASTER_KEY"
+ end
+
+ def credentials_template
+ "# aws:\n# access_key_id: 123\n# secret_access_key: 345\n\n" +
+ "# Used as the base secret for all MessageVerifiers in Rails, including the one protecting cookies.\n" +
+ "secret_key_base: #{SecureRandom.hex(64)}"
+ end
+ end
+ end
+end
diff --git a/railties/lib/rails/generators/rails/encrypted_file/encrypted_file_generator.rb b/railties/lib/rails/generators/rails/encrypted_file/encrypted_file_generator.rb
new file mode 100644
index 0000000000..ddce5f6fe2
--- /dev/null
+++ b/railties/lib/rails/generators/rails/encrypted_file/encrypted_file_generator.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+require "rails/generators/base"
+require "active_support/encrypted_file"
+
+module Rails
+ module Generators
+ class EncryptedFileGenerator < Base
+ def add_encrypted_file(file_path, key_path)
+ unless File.exist?(file_path)
+ say "Adding #{file_path} to store encrypted content."
+ say ""
+ say "The following content has been encrypted with the encryption key:"
+ say ""
+ say template, :on_green
+ say ""
+
+ add_encrypted_file_silently(file_path, key_path)
+
+ say "You can edit encrypted file with `bin/rails encrypted:edit #{file_path}`."
+ say ""
+ end
+ end
+
+ def add_encrypted_file_silently(file_path, key_path, template = encrypted_file_template)
+ unless File.exist?(file_path)
+ setup = { content_path: file_path, key_path: key_path, env_key: "RAILS_MASTER_KEY" }
+ ActiveSupport::EncryptedFile.new(setup).write(template)
+ end
+ end
+
+ private
+ def encrypted_file_template
+ "# aws:\n# access_key_id: 123\n# secret_access_key: 345\n\n"
+ end
+ end
+ end
+end
diff --git a/railties/lib/rails/generators/rails/encrypted_secrets/encrypted_secrets_generator.rb b/railties/lib/rails/generators/rails/encrypted_secrets/encrypted_secrets_generator.rb
deleted file mode 100644
index 1da2fbc1a5..0000000000
--- a/railties/lib/rails/generators/rails/encrypted_secrets/encrypted_secrets_generator.rb
+++ /dev/null
@@ -1,70 +0,0 @@
-require "rails/generators/base"
-require "rails/secrets"
-
-module Rails
- module Generators
- class EncryptedSecretsGenerator < Base
- def add_secrets_key_file
- unless File.exist?("config/secrets.yml.key") || File.exist?("config/secrets.yml.enc")
- key = Rails::Secrets.generate_key
-
- say "Adding config/secrets.yml.key to store the encryption key: #{key}"
- say ""
- say "Save this in a password manager your team can access."
- say ""
- say "If you lose the key, no one, including you, can access any encrypted secrets."
-
- say ""
- create_file "config/secrets.yml.key", key
- say ""
- end
- end
-
- def ignore_key_file
- if File.exist?(".gitignore")
- unless File.read(".gitignore").include?(key_ignore)
- say "Ignoring config/secrets.yml.key so it won't end up in Git history:"
- say ""
- append_to_file ".gitignore", key_ignore
- say ""
- end
- else
- say "IMPORTANT: Don't commit config/secrets.yml.key. Add this to your ignore file:"
- say key_ignore, :on_green
- say ""
- end
- end
-
- def add_encrypted_secrets_file
- unless (defined?(@@skip_secrets_file) && @@skip_secrets_file) || File.exist?("config/secrets.yml.enc")
- say "Adding config/secrets.yml.enc to store secrets that needs to be encrypted."
- say ""
- say "For now the file contains this but it's been encrypted with the generated key:"
- say ""
- say Secrets.template, :on_green
- say ""
-
- Secrets.write(Secrets.template)
-
- say "You can edit encrypted secrets with `bin/rails secrets:edit`."
- say ""
- end
-
- say "Add this to your config/environments/production.rb:"
- say "config.read_encrypted_secrets = true"
- end
-
- def self.skip_secrets_file
- @@skip_secrets_file = true
- yield
- ensure
- @@skip_secrets_file = false
- end
-
- private
- def key_ignore
- [ "", "# Ignore encrypted secrets key file.", "config/secrets.yml.key", "" ].join("\n")
- end
- end
- end
-end
diff --git a/railties/lib/rails/generators/rails/encryption_key_file/encryption_key_file_generator.rb b/railties/lib/rails/generators/rails/encryption_key_file/encryption_key_file_generator.rb
new file mode 100644
index 0000000000..a396a9661f
--- /dev/null
+++ b/railties/lib/rails/generators/rails/encryption_key_file/encryption_key_file_generator.rb
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+
+require "pathname"
+require "rails/generators/base"
+require "active_support/encrypted_file"
+
+module Rails
+ module Generators
+ class EncryptionKeyFileGenerator < Base
+ def add_key_file(key_path)
+ key_path = Pathname.new(key_path)
+
+ unless key_path.exist?
+ key = ActiveSupport::EncryptedFile.generate_key
+
+ log "Adding #{key_path} to store the encryption key: #{key}"
+ log ""
+ log "Save this in a password manager your team can access."
+ log ""
+ log "If you lose the key, no one, including you, can access anything encrypted with it."
+
+ log ""
+ add_key_file_silently(key_path, key)
+ log ""
+ end
+ end
+
+ def add_key_file_silently(key_path, key = nil)
+ create_file key_path, key || ActiveSupport::EncryptedFile.generate_key
+ end
+
+ def ignore_key_file(key_path, ignore: key_ignore(key_path))
+ if File.exist?(".gitignore")
+ unless File.read(".gitignore").include?(ignore)
+ log "Ignoring #{key_path} so it won't end up in Git history:"
+ log ""
+ append_to_file ".gitignore", ignore
+ log ""
+ end
+ else
+ log "IMPORTANT: Don't commit #{key_path}. Add this to your ignore file:"
+ log ignore, :on_green
+ log ""
+ end
+ end
+
+ def ignore_key_file_silently(key_path, ignore: key_ignore(key_path))
+ append_to_file ".gitignore", ignore if File.exist?(".gitignore")
+ end
+
+ private
+ def key_ignore(key_path)
+ [ "", "/#{key_path}", "" ].join("\n")
+ end
+ end
+ end
+end
diff --git a/railties/lib/rails/generators/rails/generator/generator_generator.rb b/railties/lib/rails/generators/rails/generator/generator_generator.rb
index 299a7da5f1..747acd68d1 100644
--- a/railties/lib/rails/generators/rails/generator/generator_generator.rb
+++ b/railties/lib/rails/generators/rails/generator/generator_generator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Rails
module Generators
class GeneratorGenerator < NamedBase # :nodoc:
diff --git a/railties/lib/rails/generators/rails/helper/helper_generator.rb b/railties/lib/rails/generators/rails/helper/helper_generator.rb
index e48b1b6fb3..3837c10ca0 100644
--- a/railties/lib/rails/generators/rails/helper/helper_generator.rb
+++ b/railties/lib/rails/generators/rails/helper/helper_generator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Rails
module Generators
class HelperGenerator < NamedBase # :nodoc:
diff --git a/railties/lib/rails/generators/rails/helper/templates/helper.rb b/railties/lib/rails/generators/rails/helper/templates/helper.rb.tt
index b4173151b4..b4173151b4 100644
--- a/railties/lib/rails/generators/rails/helper/templates/helper.rb
+++ b/railties/lib/rails/generators/rails/helper/templates/helper.rb.tt
diff --git a/railties/lib/rails/generators/rails/integration_test/integration_test_generator.rb b/railties/lib/rails/generators/rails/integration_test/integration_test_generator.rb
index 70770ddcb8..975dd8b90c 100644
--- a/railties/lib/rails/generators/rails/integration_test/integration_test_generator.rb
+++ b/railties/lib/rails/generators/rails/integration_test/integration_test_generator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Rails
module Generators
class IntegrationTestGenerator < NamedBase # :nodoc:
diff --git a/railties/lib/rails/generators/rails/master_key/master_key_generator.rb b/railties/lib/rails/generators/rails/master_key/master_key_generator.rb
new file mode 100644
index 0000000000..7f57340c11
--- /dev/null
+++ b/railties/lib/rails/generators/rails/master_key/master_key_generator.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+require "pathname"
+require "rails/generators/base"
+require "rails/generators/rails/encryption_key_file/encryption_key_file_generator"
+require "active_support/encrypted_file"
+
+module Rails
+ module Generators
+ class MasterKeyGenerator < Base
+ MASTER_KEY_PATH = Pathname.new("config/master.key")
+
+ def add_master_key_file
+ unless MASTER_KEY_PATH.exist?
+ key = ActiveSupport::EncryptedFile.generate_key
+
+ log "Adding #{MASTER_KEY_PATH} to store the master encryption key: #{key}"
+ log ""
+ log "Save this in a password manager your team can access."
+ log ""
+ log "If you lose the key, no one, including you, can access anything encrypted with it."
+
+ log ""
+ add_master_key_file_silently(key)
+ log ""
+ end
+ end
+
+ def add_master_key_file_silently(key = nil)
+ key_file_generator.add_key_file_silently(MASTER_KEY_PATH, key)
+ end
+
+ def ignore_master_key_file
+ key_file_generator.ignore_key_file(MASTER_KEY_PATH, ignore: key_ignore)
+ end
+
+ def ignore_master_key_file_silently
+ key_file_generator.ignore_key_file_silently(MASTER_KEY_PATH, ignore: key_ignore)
+ end
+
+ private
+ def key_file_generator
+ EncryptionKeyFileGenerator.new([], options)
+ end
+
+ def key_ignore
+ [ "", "# Ignore master key for decrypting credentials and more.", "/#{MASTER_KEY_PATH}", "" ].join("\n")
+ end
+ end
+ end
+end
diff --git a/railties/lib/rails/generators/rails/migration/migration_generator.rb b/railties/lib/rails/generators/rails/migration/migration_generator.rb
index fca2a8fef4..c331c135e3 100644
--- a/railties/lib/rails/generators/rails/migration/migration_generator.rb
+++ b/railties/lib/rails/generators/rails/migration/migration_generator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Rails
module Generators
class MigrationGenerator < NamedBase # :nodoc:
diff --git a/railties/lib/rails/generators/rails/model/model_generator.rb b/railties/lib/rails/generators/rails/model/model_generator.rb
index c32a8a079a..de4de2cae2 100644
--- a/railties/lib/rails/generators/rails/model/model_generator.rb
+++ b/railties/lib/rails/generators/rails/model/model_generator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rails/generators/model_helpers"
module Rails
diff --git a/railties/lib/rails/generators/rails/plugin/plugin_generator.rb b/railties/lib/rails/generators/rails/plugin/plugin_generator.rb
index 118e44d9d0..a83c911806 100644
--- a/railties/lib/rails/generators/rails/plugin/plugin_generator.rb
+++ b/railties/lib/rails/generators/rails/plugin/plugin_generator.rb
@@ -1,4 +1,5 @@
-require "active_support/core_ext/hash/slice"
+# frozen_string_literal: true
+
require "rails/generators/rails/app/app_generator"
require "date"
@@ -60,7 +61,12 @@ module Rails
template "lib/%namespaced_name%.rb"
template "lib/tasks/%namespaced_name%_tasks.rake"
template "lib/%namespaced_name%/version.rb"
- template "lib/%namespaced_name%/engine.rb" if engine?
+
+ if engine?
+ template "lib/%namespaced_name%/engine.rb"
+ else
+ template "lib/%namespaced_name%/railtie.rb"
+ end
end
def config
@@ -71,8 +77,8 @@ module Rails
template "test/test_helper.rb"
template "test/%namespaced_name%_test.rb"
append_file "Rakefile", <<-EOF
-#{rakefile_test_tasks}
+#{rakefile_test_tasks}
task default: :test
EOF
if engine?
@@ -81,18 +87,18 @@ task default: :test
end
PASSTHROUGH_OPTIONS = [
- :skip_active_record, :skip_action_mailer, :skip_javascript, :skip_sprockets, :database,
- :javascript, :quiet, :pretend, :force, :skip
+ :skip_active_record, :skip_active_storage, :skip_action_mailer, :skip_javascript, :skip_action_cable, :skip_sprockets, :database,
+ :javascript, :skip_yarn, :api, :quiet, :pretend, :skip
]
def generate_test_dummy(force = false)
- opts = (options || {}).slice(*PASSTHROUGH_OPTIONS)
+ opts = (options.dup || {}).keep_if { |k, _| PASSTHROUGH_OPTIONS.map(&:to_s).include?(k) }
opts[:force] = force
opts[:skip_bundle] = true
- opts[:api] = options.api?
opts[:skip_listen] = true
opts[:skip_git] = true
opts[:skip_turbolinks] = true
+ opts[:dummy_app] = true
invoke Rails::Generators::AppGenerator,
[ File.expand_path(dummy_path, destination_root) ], opts
@@ -115,7 +121,6 @@ task default: :test
def test_dummy_clean
inside dummy_path do
remove_file "db/seeds.rb"
- remove_file "doc"
remove_file "Gemfile"
remove_file "lib/tasks"
remove_file "public/robots.txt"
@@ -162,7 +167,7 @@ task default: :test
gemfile_in_app_path = File.join(rails_app_path, "Gemfile")
if File.exist? gemfile_in_app_path
- entry = "gem '#{name}', path: '#{relative_path}'"
+ entry = "\ngem '#{name}', path: '#{relative_path}'"
append_file gemfile_in_app_path, entry
end
end
@@ -258,6 +263,10 @@ task default: :test
public_task :apply_rails_template
def run_after_bundle_callbacks
+ unless @after_bundle_callbacks.empty?
+ ActiveSupport::Deprecation.warn("`after_bundle` is deprecated and will be removed in the next version of Rails. ")
+ end
+
@after_bundle_callbacks.each do |callback|
callback.call
end
diff --git a/railties/lib/rails/generators/rails/plugin/templates/%name%.gemspec b/railties/lib/rails/generators/rails/plugin/templates/%name%.gemspec.tt
index 9a8c4bf098..9a8c4bf098 100644
--- a/railties/lib/rails/generators/rails/plugin/templates/%name%.gemspec
+++ b/railties/lib/rails/generators/rails/plugin/templates/%name%.gemspec.tt
diff --git a/railties/lib/rails/generators/rails/plugin/templates/Gemfile b/railties/lib/rails/generators/rails/plugin/templates/Gemfile.tt
index 22a4548ff2..290259b4db 100644
--- a/railties/lib/rails/generators/rails/plugin/templates/Gemfile
+++ b/railties/lib/rails/generators/rails/plugin/templates/Gemfile.tt
@@ -1,4 +1,5 @@
source 'https://rubygems.org'
+git_source(:github) { |repo| "https://github.com/#{repo}.git" }
<% if options[:skip_gemspec] -%>
<%= '# ' if options.dev? || options.edge? -%>gem 'rails', '<%= Array(rails_version_specifier).join("', '") %>'
diff --git a/railties/lib/rails/generators/rails/plugin/templates/MIT-LICENSE b/railties/lib/rails/generators/rails/plugin/templates/MIT-LICENSE.tt
index ff2fb3ba4e..ff2fb3ba4e 100644
--- a/railties/lib/rails/generators/rails/plugin/templates/MIT-LICENSE
+++ b/railties/lib/rails/generators/rails/plugin/templates/MIT-LICENSE.tt
diff --git a/railties/lib/rails/generators/rails/plugin/templates/README.md b/railties/lib/rails/generators/rails/plugin/templates/README.md.tt
index 9d2b74416e..1632409bea 100644
--- a/railties/lib/rails/generators/rails/plugin/templates/README.md
+++ b/railties/lib/rails/generators/rails/plugin/templates/README.md.tt
@@ -25,4 +25,4 @@ $ gem install <%= name %>
Contribution directions go here.
## License
-The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
+The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
diff --git a/railties/lib/rails/generators/rails/plugin/templates/Rakefile b/railties/lib/rails/generators/rails/plugin/templates/Rakefile.tt
index 3581dd401a..f3efe21cf1 100644
--- a/railties/lib/rails/generators/rails/plugin/templates/Rakefile
+++ b/railties/lib/rails/generators/rails/plugin/templates/Rakefile.tt
@@ -13,17 +13,16 @@ RDoc::Task.new(:rdoc) do |rdoc|
rdoc.rdoc_files.include('README.md')
rdoc.rdoc_files.include('lib/**/*.rb')
end
-
<% if engine? && !options[:skip_active_record] && with_dummy_app? -%>
+
APP_RAKEFILE = File.expand_path("<%= dummy_path -%>/Rakefile", __dir__)
load 'rails/tasks/engine.rake'
-<% end %>
-
+<% end -%>
<% if engine? -%>
-load 'rails/tasks/statistics.rake'
-<% end %>
+load 'rails/tasks/statistics.rake'
+<% end -%>
<% unless options[:skip_gemspec] -%>
require 'bundler/gem_tasks'
-<% end %>
+<% end -%>
diff --git a/railties/lib/rails/generators/rails/plugin/templates/bin/rails.tt b/railties/lib/rails/generators/rails/plugin/templates/bin/rails.tt
index ffa277e334..b3264509fc 100644
--- a/railties/lib/rails/generators/rails/plugin/templates/bin/rails.tt
+++ b/railties/lib/rails/generators/rails/plugin/templates/bin/rails.tt
@@ -3,11 +3,28 @@
ENGINE_ROOT = File.expand_path('..', __dir__)
ENGINE_PATH = File.expand_path('../lib/<%= namespaced_name -%>/engine', __dir__)
+<% if with_dummy_app? -%>
APP_PATH = File.expand_path('../<%= dummy_path -%>/config/application', __dir__)
+<% end -%>
# Set up gems listed in the Gemfile.
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
+<% if include_all_railties? -%>
require 'rails/all'
+<% else -%>
+require "rails"
+# Pick the frameworks you want:
+require "active_model/railtie"
+require "active_job/railtie"
+<%= comment_if :skip_active_record %>require "active_record/railtie"
+require "action_controller/railtie"
+<%= comment_if :skip_action_mailer %>require "action_mailer/railtie"
+require "action_view/railtie"
+require "active_storage/engine"
+<%= comment_if :skip_action_cable %>require "action_cable/engine"
+<%= comment_if :skip_sprockets %>require "sprockets/railtie"
+<%= comment_if :skip_test %>require "rails/test_unit/railtie"
+<% end -%>
require 'rails/engine/commands'
diff --git a/railties/lib/rails/generators/rails/plugin/templates/config/routes.rb b/railties/lib/rails/generators/rails/plugin/templates/config/routes.rb.tt
index 154452bfe5..154452bfe5 100644
--- a/railties/lib/rails/generators/rails/plugin/templates/config/routes.rb
+++ b/railties/lib/rails/generators/rails/plugin/templates/config/routes.rb.tt
diff --git a/railties/lib/rails/generators/rails/plugin/templates/gitignore b/railties/lib/rails/generators/rails/plugin/templates/gitignore
deleted file mode 100644
index 54c78d7927..0000000000
--- a/railties/lib/rails/generators/rails/plugin/templates/gitignore
+++ /dev/null
@@ -1,9 +0,0 @@
-.bundle/
-log/*.log
-pkg/
-<% unless options[:skip_test] && options[:dummy_path] == 'test/dummy' -%>
-<%= dummy_path %>/db/*.sqlite3
-<%= dummy_path %>/db/*.sqlite3-journal
-<%= dummy_path %>/log/*.log
-<%= dummy_path %>/tmp/
-<% end -%>
diff --git a/railties/lib/rails/generators/rails/plugin/templates/gitignore.tt b/railties/lib/rails/generators/rails/plugin/templates/gitignore.tt
new file mode 100644
index 0000000000..7a68da5c4b
--- /dev/null
+++ b/railties/lib/rails/generators/rails/plugin/templates/gitignore.tt
@@ -0,0 +1,18 @@
+.bundle/
+log/*.log
+pkg/
+<% if with_dummy_app? -%>
+<% if sqlite3? -%>
+<%= dummy_path %>/db/*.sqlite3
+<%= dummy_path %>/db/*.sqlite3-journal
+<% end -%>
+<%= dummy_path %>/log/*.log
+<% unless options[:skip_yarn] -%>
+<%= dummy_path %>/node_modules/
+<%= dummy_path %>/yarn-error.log
+<% end -%>
+<% unless skip_active_storage? -%>
+<%= dummy_path %>/storage/
+<% end -%>
+<%= dummy_path %>/tmp/
+<% end -%>
diff --git a/railties/lib/rails/generators/rails/plugin/templates/lib/%namespaced_name%.rb b/railties/lib/rails/generators/rails/plugin/templates/lib/%namespaced_name%.rb.tt
index 40b1c4cee7..3285055eb7 100644
--- a/railties/lib/rails/generators/rails/plugin/templates/lib/%namespaced_name%.rb
+++ b/railties/lib/rails/generators/rails/plugin/templates/lib/%namespaced_name%.rb.tt
@@ -1,5 +1,7 @@
<% if engine? -%>
require "<%= namespaced_name %>/engine"
-
+<% else -%>
+require "<%= namespaced_name %>/railtie"
<% end -%>
+
<%= wrap_in_modules "# Your code goes here..." %>
diff --git a/railties/lib/rails/generators/rails/plugin/templates/lib/%namespaced_name%/engine.rb b/railties/lib/rails/generators/rails/plugin/templates/lib/%namespaced_name%/engine.rb.tt
index 8938770fc4..8938770fc4 100644
--- a/railties/lib/rails/generators/rails/plugin/templates/lib/%namespaced_name%/engine.rb
+++ b/railties/lib/rails/generators/rails/plugin/templates/lib/%namespaced_name%/engine.rb.tt
diff --git a/railties/lib/rails/generators/rails/plugin/templates/lib/%namespaced_name%/railtie.rb.tt b/railties/lib/rails/generators/rails/plugin/templates/lib/%namespaced_name%/railtie.rb.tt
new file mode 100644
index 0000000000..7bdf4ee5fb
--- /dev/null
+++ b/railties/lib/rails/generators/rails/plugin/templates/lib/%namespaced_name%/railtie.rb.tt
@@ -0,0 +1,5 @@
+<%= wrap_in_modules <<-rb.strip_heredoc
+ class Railtie < ::Rails::Railtie
+ end
+rb
+%>
diff --git a/railties/lib/rails/generators/rails/plugin/templates/lib/%namespaced_name%/version.rb b/railties/lib/rails/generators/rails/plugin/templates/lib/%namespaced_name%/version.rb.tt
index b08f4ef9ae..b08f4ef9ae 100644
--- a/railties/lib/rails/generators/rails/plugin/templates/lib/%namespaced_name%/version.rb
+++ b/railties/lib/rails/generators/rails/plugin/templates/lib/%namespaced_name%/version.rb.tt
diff --git a/railties/lib/rails/generators/rails/plugin/templates/lib/tasks/%namespaced_name%_tasks.rake b/railties/lib/rails/generators/rails/plugin/templates/lib/tasks/%namespaced_name%_tasks.rake.tt
index 88a2c4120f..88a2c4120f 100644
--- a/railties/lib/rails/generators/rails/plugin/templates/lib/tasks/%namespaced_name%_tasks.rake
+++ b/railties/lib/rails/generators/rails/plugin/templates/lib/tasks/%namespaced_name%_tasks.rake.tt
diff --git a/railties/lib/rails/generators/rails/plugin/templates/rails/application.rb b/railties/lib/rails/generators/rails/plugin/templates/rails/application.rb.tt
index d03b1be878..06ffe2f1ed 100644
--- a/railties/lib/rails/generators/rails/plugin/templates/rails/application.rb
+++ b/railties/lib/rails/generators/rails/plugin/templates/rails/application.rb.tt
@@ -3,15 +3,18 @@ require_relative 'boot'
<% if include_all_railties? -%>
require 'rails/all'
<% else -%>
+require "rails"
# Pick the frameworks you want:
+require "active_model/railtie"
+require "active_job/railtie"
<%= comment_if :skip_active_record %>require "active_record/railtie"
+<%= comment_if :skip_active_storage %>require "active_storage/engine"
require "action_controller/railtie"
-require "action_view/railtie"
<%= comment_if :skip_action_mailer %>require "action_mailer/railtie"
-require "active_job/railtie"
+require "action_view/railtie"
<%= comment_if :skip_action_cable %>require "action_cable/engine"
-<%= comment_if :skip_test %>require "rails/test_unit/railtie"
<%= comment_if :skip_sprockets %>require "sprockets/railtie"
+<%= comment_if :skip_test %>require "rails/test_unit/railtie"
<% end -%>
Bundler.require(*Rails.groups)
diff --git a/railties/lib/rails/generators/rails/plugin/templates/rails/boot.rb b/railties/lib/rails/generators/rails/plugin/templates/rails/boot.rb.tt
index c9aef85d40..c9aef85d40 100644
--- a/railties/lib/rails/generators/rails/plugin/templates/rails/boot.rb
+++ b/railties/lib/rails/generators/rails/plugin/templates/rails/boot.rb.tt
diff --git a/railties/lib/rails/generators/rails/plugin/templates/rails/dummy_manifest.js b/railties/lib/rails/generators/rails/plugin/templates/rails/dummy_manifest.js.tt
index 8d21b2b6fb..03937cf8ff 100644
--- a/railties/lib/rails/generators/rails/plugin/templates/rails/dummy_manifest.js
+++ b/railties/lib/rails/generators/rails/plugin/templates/rails/dummy_manifest.js.tt
@@ -1,4 +1,3 @@
-
<% unless api? -%>
//= link_tree ../images
<% end -%>
diff --git a/railties/lib/rails/generators/rails/plugin/templates/rails/engine_manifest.js b/railties/lib/rails/generators/rails/plugin/templates/rails/engine_manifest.js.tt
index 2f23844f5e..2f23844f5e 100644
--- a/railties/lib/rails/generators/rails/plugin/templates/rails/engine_manifest.js
+++ b/railties/lib/rails/generators/rails/plugin/templates/rails/engine_manifest.js.tt
diff --git a/railties/lib/rails/generators/rails/plugin/templates/rails/javascripts.js b/railties/lib/rails/generators/rails/plugin/templates/rails/javascripts.js.tt
index e54c6461cc..f3d80c87f5 100644
--- a/railties/lib/rails/generators/rails/plugin/templates/rails/javascripts.js
+++ b/railties/lib/rails/generators/rails/plugin/templates/rails/javascripts.js.tt
@@ -10,4 +10,7 @@
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
// about supported directives.
//
+<% unless skip_active_storage? -%>
+//= require activestorage
+<% end -%>
//= require_tree .
diff --git a/railties/lib/rails/generators/rails/plugin/templates/rails/routes.rb b/railties/lib/rails/generators/rails/plugin/templates/rails/routes.rb.tt
index 694510edc0..694510edc0 100644
--- a/railties/lib/rails/generators/rails/plugin/templates/rails/routes.rb
+++ b/railties/lib/rails/generators/rails/plugin/templates/rails/routes.rb.tt
diff --git a/railties/lib/rails/generators/rails/plugin/templates/test/%namespaced_name%_test.rb b/railties/lib/rails/generators/rails/plugin/templates/test/%namespaced_name%_test.rb.tt
index 1ee05d7871..1ee05d7871 100644
--- a/railties/lib/rails/generators/rails/plugin/templates/test/%namespaced_name%_test.rb
+++ b/railties/lib/rails/generators/rails/plugin/templates/test/%namespaced_name%_test.rb.tt
diff --git a/railties/lib/rails/generators/rails/plugin/templates/test/application_system_test_case.rb b/railties/lib/rails/generators/rails/plugin/templates/test/application_system_test_case.rb.tt
index d19212abd5..d19212abd5 100644
--- a/railties/lib/rails/generators/rails/plugin/templates/test/application_system_test_case.rb
+++ b/railties/lib/rails/generators/rails/plugin/templates/test/application_system_test_case.rb.tt
diff --git a/railties/lib/rails/generators/rails/plugin/templates/test/integration/navigation_test.rb b/railties/lib/rails/generators/rails/plugin/templates/test/integration/navigation_test.rb.tt
index f5d1ec2046..29e59d8407 100644
--- a/railties/lib/rails/generators/rails/plugin/templates/test/integration/navigation_test.rb
+++ b/railties/lib/rails/generators/rails/plugin/templates/test/integration/navigation_test.rb.tt
@@ -5,4 +5,3 @@ class NavigationTest < ActionDispatch::IntegrationTest
# assert true
# end
end
-
diff --git a/railties/lib/rails/generators/rails/plugin/templates/test/test_helper.rb b/railties/lib/rails/generators/rails/plugin/templates/test/test_helper.rb.tt
index 32e8202e1c..7fa9973931 100644
--- a/railties/lib/rails/generators/rails/plugin/templates/test/test_helper.rb
+++ b/railties/lib/rails/generators/rails/plugin/templates/test/test_helper.rb.tt
@@ -1,4 +1,4 @@
-require File.expand_path("../<%= options[:dummy_path] -%>/config/environment.rb", __dir__)
+require_relative "<%= File.join('..', options[:dummy_path], 'config/environment') -%>"
<% unless options[:skip_active_record] -%>
ActiveRecord::Migrator.migrations_paths = [File.expand_path("../<%= options[:dummy_path] -%>/db/migrate", __dir__)]
<% if options[:mountable] -%>
@@ -12,9 +12,11 @@ require "rails/test_help"
Minitest.backtrace_filter = Minitest::BacktraceFilter.new
<% unless engine? -%>
+require "rails/test_unit/reporter"
Rails::TestUnitReporter.executable = 'bin/test'
<% end -%>
+<% unless options[:skip_active_record] -%>
# Load fixtures from the engine
if ActiveSupport::TestCase.respond_to?(:fixture_path=)
ActiveSupport::TestCase.fixture_path = File.expand_path("fixtures", __dir__)
@@ -22,3 +24,4 @@ if ActiveSupport::TestCase.respond_to?(:fixture_path=)
ActiveSupport::TestCase.file_fixture_path = ActiveSupport::TestCase.fixture_path + "/files"
ActiveSupport::TestCase.fixtures :all
end
+<% end -%>
diff --git a/railties/lib/rails/generators/rails/resource/USAGE b/railties/lib/rails/generators/rails/resource/USAGE
index e359cd574f..66d0ee546a 100644
--- a/railties/lib/rails/generators/rails/resource/USAGE
+++ b/railties/lib/rails/generators/rails/resource/USAGE
@@ -1,6 +1,6 @@
Description:
Stubs out a new resource including an empty model and controller suitable
- for a restful, resource-oriented application. Pass the singular model name,
+ for a RESTful, resource-oriented application. Pass the singular model name,
either CamelCased or under_scored, as the first argument, and an optional
list of attribute pairs.
diff --git a/railties/lib/rails/generators/rails/resource/resource_generator.rb b/railties/lib/rails/generators/rails/resource/resource_generator.rb
index 5ac5164af0..3ba25ef0fe 100644
--- a/railties/lib/rails/generators/rails/resource/resource_generator.rb
+++ b/railties/lib/rails/generators/rails/resource/resource_generator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rails/generators/resource_helpers"
require "rails/generators/rails/model/model_generator"
diff --git a/railties/lib/rails/generators/rails/resource_route/resource_route_generator.rb b/railties/lib/rails/generators/rails/resource_route/resource_route_generator.rb
index 42705107ae..9a92991efe 100644
--- a/railties/lib/rails/generators/rails/resource_route/resource_route_generator.rb
+++ b/railties/lib/rails/generators/rails/resource_route/resource_route_generator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Rails
module Generators
class ResourceRouteGenerator < NamedBase # :nodoc:
@@ -15,37 +17,32 @@ module Rails
def add_resource_route
return if options[:actions].present?
- # iterates over all namespaces and opens up blocks
- regular_class_path.each_with_index do |namespace, index|
- write("namespace :#{namespace} do", index + 1)
+ depth = 0
+ lines = []
+
+ # Create 'namespace' ladder
+ # namespace :foo do
+ # namespace :bar do
+ regular_class_path.each do |ns|
+ lines << indent("namespace :#{ns} do\n", depth * 2)
+ depth += 1
end
# inserts the primary resource
- write("resources :#{file_name.pluralize}", route_length + 1)
+ # Create route
+ # resources 'products'
+ lines << indent(%{resources :#{file_name.pluralize}\n}, depth * 2)
- # ends blocks
- regular_class_path.each_index do |index|
- write("end", route_length - index)
+ # Create `end` ladder
+ # end
+ # end
+ until depth.zero?
+ depth -= 1
+ lines << indent("end\n", depth * 2)
end
- # route prepends two spaces onto the front of the string that is passed, this corrects that.
- # Also it adds a \n to the end of each line, as route already adds that
- # we need to correct that too.
- route route_string[2..-2]
+ route lines.join
end
-
- private
- def route_string
- @route_string ||= ""
- end
-
- def write(str, indent)
- route_string << "#{" " * indent}#{str}\n"
- end
-
- def route_length
- regular_class_path.length
- end
end
end
end
diff --git a/railties/lib/rails/generators/rails/scaffold/scaffold_generator.rb b/railties/lib/rails/generators/rails/scaffold/scaffold_generator.rb
index 12d6bc85b2..8beb7416c0 100644
--- a/railties/lib/rails/generators/rails/scaffold/scaffold_generator.rb
+++ b/railties/lib/rails/generators/rails/scaffold/scaffold_generator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rails/generators/rails/resource/resource_generator"
module Rails
@@ -16,13 +18,10 @@ module Rails
def handle_skip
@options = @options.merge(stylesheets: false) unless options[:assets]
@options = @options.merge(stylesheet_engine: false) unless options[:stylesheets] && options[:scaffold_stylesheet]
- @options = @options.merge(system_tests: false) if options[:api]
end
hook_for :scaffold_controller, required: true
- hook_for :system_tests, as: :system
-
hook_for :assets do |assets|
invoke assets, [controller_name]
end
diff --git a/railties/lib/rails/generators/rails/scaffold_controller/scaffold_controller_generator.rb b/railties/lib/rails/generators/rails/scaffold_controller/scaffold_controller_generator.rb
index cf97c22160..7030561a33 100644
--- a/railties/lib/rails/generators/rails/scaffold_controller/scaffold_controller_generator.rb
+++ b/railties/lib/rails/generators/rails/scaffold_controller/scaffold_controller_generator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rails/generators/resource_helpers"
module Rails
diff --git a/railties/lib/rails/generators/rails/scaffold_controller/templates/api_controller.rb b/railties/lib/rails/generators/rails/scaffold_controller/templates/api_controller.rb.tt
index 400afec6dc..400afec6dc 100644
--- a/railties/lib/rails/generators/rails/scaffold_controller/templates/api_controller.rb
+++ b/railties/lib/rails/generators/rails/scaffold_controller/templates/api_controller.rb.tt
diff --git a/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb b/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb.tt
index 42b9e34274..05f1c2b2d3 100644
--- a/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb
+++ b/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb.tt
@@ -29,7 +29,7 @@ class <%= controller_class_name %>Controller < ApplicationController
@<%= singular_table_name %> = <%= orm_class.build(class_name, "#{singular_table_name}_params") %>
if @<%= orm_instance.save %>
- redirect_to @<%= singular_table_name %>, notice: <%= "'#{human_name} was successfully created.'" %>
+ redirect_to <%= redirect_resource_name %>, notice: <%= "'#{human_name} was successfully created.'" %>
else
render :new
end
@@ -38,7 +38,7 @@ class <%= controller_class_name %>Controller < ApplicationController
# PATCH/PUT <%= route_url %>/1
def update
if @<%= orm_instance.update("#{singular_table_name}_params") %>
- redirect_to @<%= singular_table_name %>, notice: <%= "'#{human_name} was successfully updated.'" %>
+ redirect_to <%= redirect_resource_name %>, notice: <%= "'#{human_name} was successfully updated.'" %>
else
render :edit
end
diff --git a/railties/lib/rails/generators/rails/system_test/system_test_generator.rb b/railties/lib/rails/generators/rails/system_test/system_test_generator.rb
index 901120e892..7169e1bd3b 100644
--- a/railties/lib/rails/generators/rails/system_test/system_test_generator.rb
+++ b/railties/lib/rails/generators/rails/system_test/system_test_generator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Rails
module Generators
class SystemTestGenerator < NamedBase # :nodoc:
diff --git a/railties/lib/rails/generators/rails/task/task_generator.rb b/railties/lib/rails/generators/rails/task/task_generator.rb
index bb96bdf0dd..b7290a7447 100644
--- a/railties/lib/rails/generators/rails/task/task_generator.rb
+++ b/railties/lib/rails/generators/rails/task/task_generator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Rails
module Generators
class TaskGenerator < NamedBase # :nodoc:
diff --git a/railties/lib/rails/generators/rails/task/templates/task.rb b/railties/lib/rails/generators/rails/task/templates/task.rb.tt
index 1e3ed5f158..1e3ed5f158 100644
--- a/railties/lib/rails/generators/rails/task/templates/task.rb
+++ b/railties/lib/rails/generators/rails/task/templates/task.rb.tt
diff --git a/railties/lib/rails/generators/resource_helpers.rb b/railties/lib/rails/generators/resource_helpers.rb
index e7cb722473..a146a8fda6 100644
--- a/railties/lib/rails/generators/resource_helpers.rb
+++ b/railties/lib/rails/generators/resource_helpers.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rails/generators/active_model"
require "rails/generators/model_helpers"
diff --git a/railties/lib/rails/generators/test_case.rb b/railties/lib/rails/generators/test_case.rb
index 575af80303..5c71bf0be9 100644
--- a/railties/lib/rails/generators/test_case.rb
+++ b/railties/lib/rails/generators/test_case.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rails/generators"
require "rails/generators/testing/behaviour"
require "rails/generators/testing/setup_and_teardown"
diff --git a/railties/lib/rails/generators/test_unit.rb b/railties/lib/rails/generators/test_unit.rb
index 722efcf492..1005ac557c 100644
--- a/railties/lib/rails/generators/test_unit.rb
+++ b/railties/lib/rails/generators/test_unit.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rails/generators/named_base"
module TestUnit # :nodoc:
diff --git a/railties/lib/rails/generators/test_unit/controller/controller_generator.rb b/railties/lib/rails/generators/test_unit/controller/controller_generator.rb
index ac528d94f1..1a9ac6bf2a 100644
--- a/railties/lib/rails/generators/test_unit/controller/controller_generator.rb
+++ b/railties/lib/rails/generators/test_unit/controller/controller_generator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rails/generators/test_unit"
module TestUnit # :nodoc:
diff --git a/railties/lib/rails/generators/test_unit/controller/templates/functional_test.rb b/railties/lib/rails/generators/test_unit/controller/templates/functional_test.rb.tt
index ff41fef9e9..ff41fef9e9 100644
--- a/railties/lib/rails/generators/test_unit/controller/templates/functional_test.rb
+++ b/railties/lib/rails/generators/test_unit/controller/templates/functional_test.rb.tt
diff --git a/railties/lib/rails/generators/test_unit/generator/generator_generator.rb b/railties/lib/rails/generators/test_unit/generator/generator_generator.rb
index 6b6e094453..19be4f2f51 100644
--- a/railties/lib/rails/generators/test_unit/generator/generator_generator.rb
+++ b/railties/lib/rails/generators/test_unit/generator/generator_generator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rails/generators/test_unit"
module TestUnit # :nodoc:
diff --git a/railties/lib/rails/generators/test_unit/generator/templates/generator_test.rb b/railties/lib/rails/generators/test_unit/generator/templates/generator_test.rb.tt
index a7f1fc4fba..a7f1fc4fba 100644
--- a/railties/lib/rails/generators/test_unit/generator/templates/generator_test.rb
+++ b/railties/lib/rails/generators/test_unit/generator/templates/generator_test.rb.tt
diff --git a/railties/lib/rails/generators/test_unit/helper/helper_generator.rb b/railties/lib/rails/generators/test_unit/helper/helper_generator.rb
index 6674a15fa3..77308dcf7d 100644
--- a/railties/lib/rails/generators/test_unit/helper/helper_generator.rb
+++ b/railties/lib/rails/generators/test_unit/helper/helper_generator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rails/generators/test_unit"
module TestUnit # :nodoc:
diff --git a/railties/lib/rails/generators/test_unit/integration/integration_generator.rb b/railties/lib/rails/generators/test_unit/integration/integration_generator.rb
index 9d065c1297..ae307c5cd9 100644
--- a/railties/lib/rails/generators/test_unit/integration/integration_generator.rb
+++ b/railties/lib/rails/generators/test_unit/integration/integration_generator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rails/generators/test_unit"
module TestUnit # :nodoc:
diff --git a/railties/lib/rails/generators/test_unit/integration/templates/integration_test.rb b/railties/lib/rails/generators/test_unit/integration/templates/integration_test.rb.tt
index 118e0f1271..118e0f1271 100644
--- a/railties/lib/rails/generators/test_unit/integration/templates/integration_test.rb
+++ b/railties/lib/rails/generators/test_unit/integration/templates/integration_test.rb.tt
diff --git a/railties/lib/rails/generators/test_unit/job/job_generator.rb b/railties/lib/rails/generators/test_unit/job/job_generator.rb
index 6975252b99..a99ce914c0 100644
--- a/railties/lib/rails/generators/test_unit/job/job_generator.rb
+++ b/railties/lib/rails/generators/test_unit/job/job_generator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rails/generators/test_unit"
module TestUnit # :nodoc:
@@ -6,7 +8,7 @@ module TestUnit # :nodoc:
check_class_collision suffix: "JobTest"
def create_test_file
- template "unit_test.rb.erb", File.join("test/jobs", class_path, "#{file_name}_job_test.rb")
+ template "unit_test.rb", File.join("test/jobs", class_path, "#{file_name}_job_test.rb")
end
end
end
diff --git a/railties/lib/rails/generators/test_unit/job/templates/unit_test.rb.erb b/railties/lib/rails/generators/test_unit/job/templates/unit_test.rb.tt
index f5351d0ec6..f5351d0ec6 100644
--- a/railties/lib/rails/generators/test_unit/job/templates/unit_test.rb.erb
+++ b/railties/lib/rails/generators/test_unit/job/templates/unit_test.rb.tt
diff --git a/railties/lib/rails/generators/test_unit/mailer/mailer_generator.rb b/railties/lib/rails/generators/test_unit/mailer/mailer_generator.rb
index 67bff8e4f9..610d47a729 100644
--- a/railties/lib/rails/generators/test_unit/mailer/mailer_generator.rb
+++ b/railties/lib/rails/generators/test_unit/mailer/mailer_generator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rails/generators/test_unit"
module TestUnit # :nodoc:
diff --git a/railties/lib/rails/generators/test_unit/mailer/templates/functional_test.rb b/railties/lib/rails/generators/test_unit/mailer/templates/functional_test.rb.tt
index a2f2d30de5..a2f2d30de5 100644
--- a/railties/lib/rails/generators/test_unit/mailer/templates/functional_test.rb
+++ b/railties/lib/rails/generators/test_unit/mailer/templates/functional_test.rb.tt
diff --git a/railties/lib/rails/generators/test_unit/mailer/templates/preview.rb b/railties/lib/rails/generators/test_unit/mailer/templates/preview.rb.tt
index b063cbc47b..b063cbc47b 100644
--- a/railties/lib/rails/generators/test_unit/mailer/templates/preview.rb
+++ b/railties/lib/rails/generators/test_unit/mailer/templates/preview.rb.tt
diff --git a/railties/lib/rails/generators/test_unit/model/model_generator.rb b/railties/lib/rails/generators/test_unit/model/model_generator.rb
index 99495d5247..02d7502592 100644
--- a/railties/lib/rails/generators/test_unit/model/model_generator.rb
+++ b/railties/lib/rails/generators/test_unit/model/model_generator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rails/generators/test_unit"
module TestUnit # :nodoc:
diff --git a/railties/lib/rails/generators/test_unit/model/templates/fixtures.yml b/railties/lib/rails/generators/test_unit/model/templates/fixtures.yml.tt
index 0681780c97..0681780c97 100644
--- a/railties/lib/rails/generators/test_unit/model/templates/fixtures.yml
+++ b/railties/lib/rails/generators/test_unit/model/templates/fixtures.yml.tt
diff --git a/railties/lib/rails/generators/test_unit/model/templates/unit_test.rb b/railties/lib/rails/generators/test_unit/model/templates/unit_test.rb.tt
index c9bc7d5b90..c9bc7d5b90 100644
--- a/railties/lib/rails/generators/test_unit/model/templates/unit_test.rb
+++ b/railties/lib/rails/generators/test_unit/model/templates/unit_test.rb.tt
diff --git a/railties/lib/rails/generators/test_unit/plugin/plugin_generator.rb b/railties/lib/rails/generators/test_unit/plugin/plugin_generator.rb
index f1c9b6da5b..0657bc2389 100644
--- a/railties/lib/rails/generators/test_unit/plugin/plugin_generator.rb
+++ b/railties/lib/rails/generators/test_unit/plugin/plugin_generator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rails/generators/test_unit"
module TestUnit # :nodoc:
diff --git a/railties/lib/rails/generators/test_unit/scaffold/scaffold_generator.rb b/railties/lib/rails/generators/test_unit/scaffold/scaffold_generator.rb
index 292db35121..b6c13b41ae 100644
--- a/railties/lib/rails/generators/test_unit/scaffold/scaffold_generator.rb
+++ b/railties/lib/rails/generators/test_unit/scaffold/scaffold_generator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rails/generators/test_unit"
require "rails/generators/resource_helpers"
@@ -11,12 +13,19 @@ module TestUnit # :nodoc:
class_option :api, type: :boolean,
desc: "Generates API functional tests"
+ class_option :system_tests, type: :string,
+ desc: "Skip system test files"
+
argument :attributes, type: :array, default: [], banner: "field:type field:type"
def create_test_files
template_file = options.api? ? "api_functional_test.rb" : "functional_test.rb"
template template_file,
File.join("test/controllers", controller_class_path, "#{controller_file_name}_controller_test.rb")
+
+ unless options.api? || options[:system_tests].nil?
+ template "system_test.rb", File.join("test/system", class_path, "#{file_name.pluralize}_test.rb")
+ end
end
def fixture_name
@@ -30,16 +39,20 @@ module TestUnit # :nodoc:
private
+ def attributes_string
+ attributes_hash.map { |k, v| "#{k}: #{v}" }.join(", ")
+ end
+
def attributes_hash
- return if attributes_names.empty?
+ return {} if attributes_names.empty?
attributes_names.map do |name|
if %w(password password_confirmation).include?(name) && attributes.any?(&:password_digest?)
- "#{name}: 'secret'"
+ ["#{name}", "'secret'"]
else
- "#{name}: @#{singular_table_name}.#{name}"
+ ["#{name}", "@#{singular_table_name}.#{name}"]
end
- end.sort.join(", ")
+ end.sort.to_h
end
end
end
diff --git a/railties/lib/rails/generators/test_unit/scaffold/templates/api_functional_test.rb b/railties/lib/rails/generators/test_unit/scaffold/templates/api_functional_test.rb.tt
index c469c188e6..f21861d8e6 100644
--- a/railties/lib/rails/generators/test_unit/scaffold/templates/api_functional_test.rb
+++ b/railties/lib/rails/generators/test_unit/scaffold/templates/api_functional_test.rb.tt
@@ -17,7 +17,7 @@ class <%= controller_class_name %>ControllerTest < ActionDispatch::IntegrationTe
test "should create <%= singular_table_name %>" do
assert_difference('<%= class_name %>.count') do
- post <%= index_helper %>_url, params: { <%= "#{singular_table_name}: { #{attributes_hash} }" %> }, as: :json
+ post <%= index_helper %>_url, params: { <%= "#{singular_table_name}: { #{attributes_string} }" %> }, as: :json
end
assert_response 201
@@ -29,7 +29,7 @@ class <%= controller_class_name %>ControllerTest < ActionDispatch::IntegrationTe
end
test "should update <%= singular_table_name %>" do
- patch <%= show_helper %>, params: { <%= "#{singular_table_name}: { #{attributes_hash} }" %> }, as: :json
+ patch <%= show_helper %>, params: { <%= "#{singular_table_name}: { #{attributes_string} }" %> }, as: :json
assert_response 200
end
diff --git a/railties/lib/rails/generators/test_unit/scaffold/templates/functional_test.rb b/railties/lib/rails/generators/test_unit/scaffold/templates/functional_test.rb.tt
index c33375b7b4..195d60be20 100644
--- a/railties/lib/rails/generators/test_unit/scaffold/templates/functional_test.rb
+++ b/railties/lib/rails/generators/test_unit/scaffold/templates/functional_test.rb.tt
@@ -22,7 +22,7 @@ class <%= controller_class_name %>ControllerTest < ActionDispatch::IntegrationTe
test "should create <%= singular_table_name %>" do
assert_difference('<%= class_name %>.count') do
- post <%= index_helper %>_url, params: { <%= "#{singular_table_name}: { #{attributes_hash} }" %> }
+ post <%= index_helper %>_url, params: { <%= "#{singular_table_name}: { #{attributes_string} }" %> }
end
assert_redirected_to <%= singular_table_name %>_url(<%= class_name %>.last)
@@ -39,7 +39,7 @@ class <%= controller_class_name %>ControllerTest < ActionDispatch::IntegrationTe
end
test "should update <%= singular_table_name %>" do
- patch <%= show_helper %>, params: { <%= "#{singular_table_name}: { #{attributes_hash} }" %> }
+ patch <%= show_helper %>, params: { <%= "#{singular_table_name}: { #{attributes_string} }" %> }
assert_redirected_to <%= singular_table_name %>_url(<%= "@#{singular_table_name}" %>)
end
diff --git a/railties/lib/rails/generators/test_unit/scaffold/templates/system_test.rb.tt b/railties/lib/rails/generators/test_unit/scaffold/templates/system_test.rb.tt
new file mode 100644
index 0000000000..f83f5a5c62
--- /dev/null
+++ b/railties/lib/rails/generators/test_unit/scaffold/templates/system_test.rb.tt
@@ -0,0 +1,49 @@
+require "application_system_test_case"
+
+<% module_namespacing do -%>
+class <%= class_name.pluralize %>Test < ApplicationSystemTestCase
+ setup do
+ @<%= singular_table_name %> = <%= fixture_name %>(:one)
+ end
+
+ test "visiting the index" do
+ visit <%= plural_table_name %>_url
+ assert_selector "h1", text: "<%= class_name.pluralize.titleize %>"
+ end
+
+ test "creating a <%= human_name %>" do
+ visit <%= plural_table_name %>_url
+ click_on "New <%= class_name.titleize %>"
+
+ <%- attributes_hash.each do |attr, value| -%>
+ fill_in "<%= attr.humanize.titleize %>", with: <%= value %>
+ <%- end -%>
+ click_on "Create <%= human_name %>"
+
+ assert_text "<%= human_name %> was successfully created"
+ click_on "Back"
+ end
+
+ test "updating a <%= human_name %>" do
+ visit <%= plural_table_name %>_url
+ click_on "Edit", match: :first
+
+ <%- attributes_hash.each do |attr, value| -%>
+ fill_in "<%= attr.humanize.titleize %>", with: <%= value %>
+ <%- end -%>
+ click_on "Update <%= human_name %>"
+
+ assert_text "<%= human_name %> was successfully updated"
+ click_on "Back"
+ end
+
+ test "destroying a <%= human_name %>" do
+ visit <%= plural_table_name %>_url
+ page.accept_confirm do
+ click_on "Destroy", match: :first
+ end
+
+ assert_text "<%= human_name %> was successfully destroyed"
+ end
+end
+<% end -%>
diff --git a/railties/lib/rails/generators/test_unit/system/system_generator.rb b/railties/lib/rails/generators/test_unit/system/system_generator.rb
index 0514957d9c..08504d4124 100644
--- a/railties/lib/rails/generators/test_unit/system/system_generator.rb
+++ b/railties/lib/rails/generators/test_unit/system/system_generator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rails/generators/test_unit"
module TestUnit # :nodoc:
diff --git a/railties/lib/rails/generators/test_unit/system/templates/application_system_test_case.rb b/railties/lib/rails/generators/test_unit/system/templates/application_system_test_case.rb.tt
index d19212abd5..d19212abd5 100644
--- a/railties/lib/rails/generators/test_unit/system/templates/application_system_test_case.rb
+++ b/railties/lib/rails/generators/test_unit/system/templates/application_system_test_case.rb.tt
diff --git a/railties/lib/rails/generators/test_unit/system/templates/system_test.rb b/railties/lib/rails/generators/test_unit/system/templates/system_test.rb.tt
index b5ce2ba5c8..b5ce2ba5c8 100644
--- a/railties/lib/rails/generators/test_unit/system/templates/system_test.rb
+++ b/railties/lib/rails/generators/test_unit/system/templates/system_test.rb.tt
diff --git a/railties/lib/rails/generators/testing/assertions.rb b/railties/lib/rails/generators/testing/assertions.rb
index 1cabf4e28c..c4cff9090b 100644
--- a/railties/lib/rails/generators/testing/assertions.rb
+++ b/railties/lib/rails/generators/testing/assertions.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Rails
module Generators
module Testing
@@ -113,7 +115,11 @@ module Rails
#
# assert_field_default_value :string, "MyString"
def assert_field_default_value(attribute_type, value)
- assert_equal(value, create_generated_attribute(attribute_type).default)
+ if value.nil?
+ assert_nil(create_generated_attribute(attribute_type).default)
+ else
+ assert_equal(value, create_generated_attribute(attribute_type).default)
+ end
end
end
end
diff --git a/railties/lib/rails/generators/testing/behaviour.rb b/railties/lib/rails/generators/testing/behaviour.rb
index ce0e42e60d..6ab88bd59f 100644
--- a/railties/lib/rails/generators/testing/behaviour.rb
+++ b/railties/lib/rails/generators/testing/behaviour.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "active_support/core_ext/class/attribute"
require "active_support/core_ext/module/delegation"
require "active_support/core_ext/hash/reverse_merge"
diff --git a/railties/lib/rails/generators/testing/setup_and_teardown.rb b/railties/lib/rails/generators/testing/setup_and_teardown.rb
index 73102a283f..4374aa5b8c 100644
--- a/railties/lib/rails/generators/testing/setup_and_teardown.rb
+++ b/railties/lib/rails/generators/testing/setup_and_teardown.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Rails
module Generators
module Testing
diff --git a/railties/lib/rails/info.rb b/railties/lib/rails/info.rb
index db08d578c0..d8f361f524 100644
--- a/railties/lib/rails/info.rb
+++ b/railties/lib/rails/info.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "cgi"
module Rails
@@ -39,7 +41,7 @@ module Rails
alias inspect to_s
def to_html
- "<table>".tap do |table|
+ "<table>".dup.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/info_controller.rb b/railties/lib/rails/info_controller.rb
index 8b553aea79..b4f4a5922a 100644
--- a/railties/lib/rails/info_controller.rb
+++ b/railties/lib/rails/info_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rails/application_controller"
require "action_dispatch/routing/inspector"
diff --git a/railties/lib/rails/initializable.rb b/railties/lib/rails/initializable.rb
index a2615d5efd..5410e17153 100644
--- a/railties/lib/rails/initializable.rb
+++ b/railties/lib/rails/initializable.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "tsort"
module Rails
diff --git a/railties/lib/rails/mailers_controller.rb b/railties/lib/rails/mailers_controller.rb
index 7ff55ef5bf..66636e5d6b 100644
--- a/railties/lib/rails/mailers_controller.rb
+++ b/railties/lib/rails/mailers_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rails/application_controller"
class Rails::MailersController < Rails::ApplicationController # :nodoc:
diff --git a/railties/lib/rails/paths.rb b/railties/lib/rails/paths.rb
index 6bdb673215..87222563fd 100644
--- a/railties/lib/rails/paths.rb
+++ b/railties/lib/rails/paths.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Rails
module Paths
# This object is an extended hash that behaves as root of the <tt>Rails::Paths</tt> system.
diff --git a/railties/lib/rails/plugin/test.rb b/railties/lib/rails/plugin/test.rb
index ff043b488e..18b6fd1757 100644
--- a/railties/lib/rails/plugin/test.rb
+++ b/railties/lib/rails/plugin/test.rb
@@ -1,7 +1,9 @@
-require "rails/test_unit/minitest_plugin"
+# frozen_string_literal: true
-Rails::TestUnitReporter.executable = "bin/test"
+require "rails/test_unit/runner"
+require "rails/test_unit/reporter"
-Minitest.run_via = :rails
+Rails::TestUnitReporter.executable = "bin/test"
-require "active_support/testing/autorun"
+Rails::TestUnit::Runner.parse_options(ARGV)
+Rails::TestUnit::Runner.run(ARGV)
diff --git a/railties/lib/rails/rack.rb b/railties/lib/rails/rack.rb
index a4c4527a72..579fb25cc4 100644
--- a/railties/lib/rails/rack.rb
+++ b/railties/lib/rails/rack.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Rails
module Rack
autoload :Logger, "rails/rack/logger"
diff --git a/railties/lib/rails/rack/logger.rb b/railties/lib/rails/rack/logger.rb
index 853fc26051..ec5212ee76 100644
--- a/railties/lib/rails/rack/logger.rb
+++ b/railties/lib/rails/rack/logger.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "active_support/core_ext/time/conversions"
require "active_support/core_ext/object/blank"
require "active_support/log_subscriber"
diff --git a/railties/lib/rails/railtie.rb b/railties/lib/rails/railtie.rb
index 3476bb0eb5..88dd932370 100644
--- a/railties/lib/rails/railtie.rb
+++ b/railties/lib/rails/railtie.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rails/initializable"
require "active_support/inflector"
require "active_support/core_ext/module/introspection"
@@ -103,6 +105,9 @@ module Rails
# end
# end
#
+ # Since filenames on the load path are shared across gems, be sure that files you load
+ # through a railtie have unique names.
+ #
# == Application and Engine
#
# An engine is nothing more than a railtie with some initializers already set. And since
diff --git a/railties/lib/rails/railtie/configurable.rb b/railties/lib/rails/railtie/configurable.rb
index 2a8295426e..7f42fae10a 100644
--- a/railties/lib/rails/railtie/configurable.rb
+++ b/railties/lib/rails/railtie/configurable.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "active_support/concern"
module Rails
diff --git a/railties/lib/rails/railtie/configuration.rb b/railties/lib/rails/railtie/configuration.rb
index aecc81c491..48853129bc 100644
--- a/railties/lib/rails/railtie/configuration.rb
+++ b/railties/lib/rails/railtie/configuration.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rails/configuration"
module Rails
diff --git a/railties/lib/rails/ruby_version_check.rb b/railties/lib/rails/ruby_version_check.rb
index b212835df7..76b6b80d28 100644
--- a/railties/lib/rails/ruby_version_check.rb
+++ b/railties/lib/rails/ruby_version_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
if RUBY_VERSION < "2.2.2" && RUBY_ENGINE == "ruby"
desc = defined?(RUBY_DESCRIPTION) ? RUBY_DESCRIPTION : "ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE})"
abort <<-end_message
diff --git a/railties/lib/rails/secrets.rb b/railties/lib/rails/secrets.rb
index c7a8676d7b..30e3478c9b 100644
--- a/railties/lib/rails/secrets.rb
+++ b/railties/lib/rails/secrets.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "yaml"
require "active_support/message_encryptor"
require "active_support/core_ext/string/strip"
@@ -30,23 +32,10 @@ module Rails
end
end
- def generate_key
- SecureRandom.hex(OpenSSL::Cipher.new(@cipher).key_len)
- end
-
def key
ENV["RAILS_MASTER_KEY"] || read_key_file || handle_missing_key
end
- def template
- <<-end_of_template.strip_heredoc
- # See `secrets.yml` for tips on generating suitable keys.
- # production:
- # external_api_key: 1466aac22e6a869134be3d09b9e89232fc2c2289
-
- end_of_template
- end
-
def encrypt(data)
encryptor.encrypt_and_sign(data)
end
@@ -68,10 +57,6 @@ module Rails
writing(read, &block)
end
- def read_template_for_editing(&block)
- writing(template, &block)
- end
-
private
def handle_missing_key
raise MissingKeyError
@@ -100,12 +85,15 @@ module Rails
end
def writing(contents)
- tmp_path = File.join(Dir.tmpdir, File.basename(path))
- File.write(tmp_path, contents)
+ tmp_file = "#{File.basename(path)}.#{Process.pid}"
+ tmp_path = File.join(Dir.tmpdir, tmp_file)
+ IO.binwrite(tmp_path, contents)
yield tmp_path
- write(File.read(tmp_path))
+ updated_contents = IO.binread(tmp_path)
+
+ write(updated_contents) if updated_contents != contents
ensure
FileUtils.rm(tmp_path) if File.exist?(tmp_path)
end
diff --git a/railties/lib/rails/source_annotation_extractor.rb b/railties/lib/rails/source_annotation_extractor.rb
index e9088c44ce..1db6c98537 100644
--- a/railties/lib/rails/source_annotation_extractor.rb
+++ b/railties/lib/rails/source_annotation_extractor.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Implements the logic behind the rake tasks for annotations like
#
# rails notes
@@ -19,7 +21,7 @@ class SourceAnnotationExtractor
end
# Registers additional directories to be included
- # SourceAnnotationExtractor::Annotation.register_directories("spec","another")
+ # SourceAnnotationExtractor::Annotation.register_directories("spec", "another")
def self.register_directories(*dirs)
directories.push(*dirs)
end
@@ -45,7 +47,7 @@ class SourceAnnotationExtractor
# 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])}] "
+ s = "[#{line.to_s.rjust(options[:indent])}] ".dup
s << "[#{tag}] " if options[:tag]
s << text
end
diff --git a/railties/lib/rails/tasks.rb b/railties/lib/rails/tasks.rb
index c0a50e5bda..2f644a20c9 100644
--- a/railties/lib/rails/tasks.rb
+++ b/railties/lib/rails/tasks.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rake"
# Load Rails Rakefile extensions
diff --git a/railties/lib/rails/tasks/annotations.rake b/railties/lib/rails/tasks/annotations.rake
index 9a69eb9934..93bc66e2db 100644
--- a/railties/lib/rails/tasks/annotations.rake
+++ b/railties/lib/rails/tasks/annotations.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rails/source_annotation_extractor"
desc "Enumerate all annotations (use notes:optimize, :fixme, :todo for focus)"
diff --git a/railties/lib/rails/tasks/dev.rake b/railties/lib/rails/tasks/dev.rake
index 334e968123..5aea6f7dc5 100644
--- a/railties/lib/rails/tasks/dev.rake
+++ b/railties/lib/rails/tasks/dev.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rails/dev_caching"
namespace :dev do
diff --git a/railties/lib/rails/tasks/engine.rake b/railties/lib/rails/tasks/engine.rake
index 177b138090..9db9d78ec4 100644
--- a/railties/lib/rails/tasks/engine.rake
+++ b/railties/lib/rails/tasks/engine.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
task "load_app" do
namespace :app do
load APP_RAKEFILE
@@ -68,6 +70,9 @@ namespace :db do
desc "Retrieves the current schema version number"
app_task "version"
+
+ # desc 'Load the test schema'
+ app_task "test:prepare"
end
def find_engine_path(path)
diff --git a/railties/lib/rails/tasks/framework.rake b/railties/lib/rails/tasks/framework.rake
index 80720a42ff..7dfcd14bd0 100644
--- a/railties/lib/rails/tasks/framework.rake
+++ b/railties/lib/rails/tasks/framework.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
namespace :app do
desc "Update configs and some other initially generated files (or use just update:configs or update:bin)"
task update: [ "update:configs", "update:bin", "update:upgrade_guide_info" ]
@@ -9,7 +11,7 @@ namespace :app do
template = File.expand_path(template) if template !~ %r{\A[A-Za-z][A-Za-z0-9+\-\.]*://}
require "rails/generators"
require "rails/generators/rails/app/app_generator"
- generator = Rails::Generators::AppGenerator.new [Rails.root], {}, destination_root: Rails.root
+ generator = Rails::Generators::AppGenerator.new [Rails.root], {}, { destination_root: Rails.root }
generator.apply template, verbose: false
end
@@ -36,38 +38,21 @@ namespace :app do
end
namespace :update do
- class RailsUpdate
- def self.invoke_from_app_generator(method)
- app_generator.send(method)
- end
-
- def self.app_generator
- @app_generator ||= begin
- require "rails/generators"
- require "rails/generators/rails/app/app_generator"
- gen = Rails::Generators::AppGenerator.new ["rails"],
- { api: !!Rails.application.config.api_only, update: true },
- destination_root: Rails.root
- File.exist?(Rails.root.join("config", "application.rb")) ?
- gen.send(:app_const) : gen.send(:valid_const?)
- gen
- end
- end
- end
+ require "rails/app_updater"
# desc "Update config/boot.rb from your current rails install"
task :configs do
- RailsUpdate.invoke_from_app_generator :create_boot_file
- RailsUpdate.invoke_from_app_generator :update_config_files
+ Rails::AppUpdater.invoke_from_app_generator :create_boot_file
+ Rails::AppUpdater.invoke_from_app_generator :update_config_files
end
# desc "Adds new executables to the application bin/ directory"
task :bin do
- RailsUpdate.invoke_from_app_generator :update_bin_files
+ Rails::AppUpdater.invoke_from_app_generator :update_bin_files
end
task :upgrade_guide_info do
- RailsUpdate.invoke_from_app_generator :display_upgrade_guide_info
+ Rails::AppUpdater.invoke_from_app_generator :display_upgrade_guide_info
end
end
end
diff --git a/railties/lib/rails/tasks/initializers.rake b/railties/lib/rails/tasks/initializers.rake
index 6522f2ae5a..ae85cb0f86 100644
--- a/railties/lib/rails/tasks/initializers.rake
+++ b/railties/lib/rails/tasks/initializers.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
desc "Print out all defined initializers in the order they are invoked by Rails."
task initializers: :environment do
Rails.application.initializers.tsort_each do |initializer|
diff --git a/railties/lib/rails/tasks/log.rake b/railties/lib/rails/tasks/log.rake
index ba796845d7..e219277d23 100644
--- a/railties/lib/rails/tasks/log.rake
+++ b/railties/lib/rails/tasks/log.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
namespace :log do
##
diff --git a/railties/lib/rails/tasks/middleware.rake b/railties/lib/rails/tasks/middleware.rake
index fd98be1ea9..3a7f86fdcb 100644
--- a/railties/lib/rails/tasks/middleware.rake
+++ b/railties/lib/rails/tasks/middleware.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
desc "Prints out your Rack middleware stack"
task middleware: :environment do
Rails.configuration.middleware.each do |middleware|
diff --git a/railties/lib/rails/tasks/misc.rake b/railties/lib/rails/tasks/misc.rake
index 29ea0ff804..e7786aa622 100644
--- a/railties/lib/rails/tasks/misc.rake
+++ b/railties/lib/rails/tasks/misc.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
desc "Generate a cryptographically secure secret key (this is typically used to generate a secret for cookie sessions)."
task :secret do
require "securerandom"
diff --git a/railties/lib/rails/tasks/restart.rake b/railties/lib/rails/tasks/restart.rake
index 03177d9954..074e3e89a1 100644
--- a/railties/lib/rails/tasks/restart.rake
+++ b/railties/lib/rails/tasks/restart.rake
@@ -1,8 +1,9 @@
+# frozen_string_literal: true
+
desc "Restart app by touching tmp/restart.txt"
task :restart do
verbose(false) do
mkdir_p "tmp"
touch "tmp/restart.txt"
- rm_f "tmp/pids/server.pid"
end
end
diff --git a/railties/lib/rails/tasks/routes.rake b/railties/lib/rails/tasks/routes.rake
index 215fb2ceb5..403286d280 100644
--- a/railties/lib/rails/tasks/routes.rake
+++ b/railties/lib/rails/tasks/routes.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "optparse"
desc "Print out all defined routes in match order, with names. Target specific controller with -c option, or grep routes using -g option"
diff --git a/railties/lib/rails/tasks/statistics.rake b/railties/lib/rails/tasks/statistics.rake
index cb569be58b..594db91eec 100644
--- a/railties/lib/rails/tasks/statistics.rake
+++ b/railties/lib/rails/tasks/statistics.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# While global constants are bad, many 3rd party tools depend on this one (e.g
# rspec-rails & cucumber-rails). So a deprecation warning is needed if we want
# to remove it.
diff --git a/railties/lib/rails/tasks/tmp.rake b/railties/lib/rails/tasks/tmp.rake
index d42a890cb6..7340b41ee4 100644
--- a/railties/lib/rails/tasks/tmp.rake
+++ b/railties/lib/rails/tasks/tmp.rake
@@ -1,6 +1,8 @@
+# frozen_string_literal: true
+
namespace :tmp do
- desc "Clear cache and socket files from tmp/ (narrow w/ tmp:cache:clear, tmp:sockets:clear)"
- task clear: ["tmp:cache:clear", "tmp:sockets:clear"]
+ desc "Clear cache, socket and screenshot files from tmp/ (narrow w/ tmp:cache:clear, tmp:sockets:clear, tmp:screenshots:clear)"
+ task clear: ["tmp:cache:clear", "tmp:sockets:clear", "tmp:screenshots:clear"]
tmp_dirs = [ "tmp/cache",
"tmp/sockets",
@@ -32,4 +34,11 @@ namespace :tmp do
rm Dir["tmp/pids/[^.]*"], verbose: false
end
end
+
+ namespace :screenshots do
+ # desc "Clears all files in tmp/screenshots"
+ task :clear do
+ rm Dir["tmp/screenshots/[^.]*"], verbose: false
+ end
+ end
end
diff --git a/railties/lib/rails/tasks/yarn.rake b/railties/lib/rails/tasks/yarn.rake
index 87476b1b8c..48da7ffc51 100644
--- a/railties/lib/rails/tasks/yarn.rake
+++ b/railties/lib/rails/tasks/yarn.rake
@@ -1,7 +1,9 @@
+# frozen_string_literal: true
+
namespace :yarn do
desc "Install all JavaScript dependencies as specified via Yarn"
task :install do
- system("./bin/yarn install --no-progress")
+ system("./bin/yarn install --no-progress --production")
end
end
diff --git a/railties/lib/rails/test_help.rb b/railties/lib/rails/test_help.rb
index 81537d813e..732c5c1e1f 100644
--- a/railties/lib/rails/test_help.rb
+++ b/railties/lib/rails/test_help.rb
@@ -1,8 +1,9 @@
+# frozen_string_literal: true
+
# Make double-sure the RAILS_ENV is not set to production,
# so fixtures aren't loaded into that environment
abort("Abort testing: Your Rails environment is running in production mode!") if Rails.env.production?
-require "rails/test_unit/minitest_plugin"
require "active_support/test_case"
require "action_controller"
require "action_controller/test_case"
diff --git a/railties/lib/rails/test_unit/line_filtering.rb b/railties/lib/rails/test_unit/line_filtering.rb
index 32ba744701..f8ca77fe4a 100644
--- a/railties/lib/rails/test_unit/line_filtering.rb
+++ b/railties/lib/rails/test_unit/line_filtering.rb
@@ -1,78 +1,13 @@
-require "method_source"
+# frozen_string_literal: true
+
+require "rails/test_unit/runner"
module Rails
module LineFiltering # :nodoc:
def run(reporter, options = {})
- if options[:patterns] && options[:patterns].any? { |p| p =~ /:\d+/ }
- options[:filter] = \
- CompositeFilter.new(self, options[:filter], options[:patterns])
- end
+ options[:filter] = Rails::TestUnit::Runner.compose_filter(self, options[:filter])
super
end
end
-
- class CompositeFilter # :nodoc:
- attr_reader :named_filter
-
- def initialize(runnable, filter, patterns)
- @runnable = runnable
- @named_filter = derive_named_filter(filter)
- @filters = [ @named_filter, *derive_line_filters(patterns) ].compact
- end
-
- # Minitest uses === to find matching filters.
- def ===(method)
- @filters.any? { |filter| filter === method }
- end
-
- private
- def derive_named_filter(filter)
- if filter.respond_to?(:named_filter)
- filter.named_filter
- elsif filter =~ %r%/(.*)/% # Regexp filtering copied from Minitest.
- Regexp.new $1
- elsif filter.is_a?(String)
- filter
- end
- end
-
- def derive_line_filters(patterns)
- patterns.flat_map do |file_and_line|
- file, *lines = file_and_line.split(":")
-
- if lines.empty?
- Filter.new(@runnable, file, nil) if file
- else
- lines.map { |line| Filter.new(@runnable, file, line) }
- end
- end
- end
- end
-
- class Filter # :nodoc:
- def initialize(runnable, file, line)
- @runnable, @file = runnable, File.expand_path(file)
- @line = line.to_i if line
- end
-
- def ===(method)
- return unless @runnable.method_defined?(method)
-
- if @line
- test_file, test_range = definition_for(@runnable.instance_method(method))
- test_file == @file && test_range.include?(@line)
- else
- @runnable.instance_method(method).source_location.first == @file
- end
- end
-
- private
- def definition_for(method)
- file, start_line = method.source_location
- end_line = method.source.count("\n") + start_line - 1
-
- return file, start_line..end_line
- end
- end
end
diff --git a/railties/lib/rails/test_unit/minitest_plugin.rb b/railties/lib/rails/test_unit/minitest_plugin.rb
deleted file mode 100644
index 5d0cf1305f..0000000000
--- a/railties/lib/rails/test_unit/minitest_plugin.rb
+++ /dev/null
@@ -1,145 +0,0 @@
-require "active_support/core_ext/module/attribute_accessors"
-require "rails/test_unit/reporter"
-require "rails/test_unit/test_requirer"
-require "shellwords"
-
-module Minitest
- class SuppressedSummaryReporter < SummaryReporter
- # Disable extra failure output after a run if output is inline.
- def aggregated_results(*)
- super unless options[:output_inline]
- end
- end
-
- def self.plugin_rails_options(opts, options)
- executable = ::Rails::TestUnitReporter.executable
- opts.separator ""
- opts.separator "Usage: #{executable} [options] [files or directories]"
- opts.separator "You can run a single test by appending a line number to a filename:"
- opts.separator ""
- opts.separator " #{executable} test/models/user_test.rb:27"
- opts.separator ""
- opts.separator "You can run multiple files and directories at the same time:"
- opts.separator ""
- opts.separator " #{executable} test/controllers test/integration/login_test.rb"
- opts.separator ""
- opts.separator "By default test failures and errors are reported inline during a run."
- opts.separator ""
-
- opts.separator "Rails options:"
- opts.on("-e", "--environment ENV",
- "Run tests in the ENV environment") do |env|
- options[:environment] = env.strip
- end
-
- opts.on("-b", "--backtrace",
- "Show the complete backtrace") do
- options[:full_backtrace] = true
- end
-
- opts.on("-d", "--defer-output",
- "Output test failures and errors after the test run") do
- options[:output_inline] = false
- end
-
- opts.on("-f", "--fail-fast",
- "Abort test run on first failure or error") do
- options[:fail_fast] = true
- end
-
- opts.on("-c", "--[no-]color",
- "Enable color in the output") do |value|
- options[:color] = value
- end
-
- opts.on("-w", "--warnings",
- "Enable ruby warnings") do
- $VERBOSE = true
- end
-
- options[:color] = true
- options[:output_inline] = true
- options[:patterns] = opts.order! unless run_via.rake?
- end
-
- def self.rake_run(patterns, exclude_patterns = []) # :nodoc:
- self.run_via = :rake unless run_via.set?
- ::Rails::TestRequirer.require_files(patterns, exclude_patterns)
- autorun
- end
-
- module RunRespectingRakeTestopts
- def run(args = [])
- if run_via.rake?
- args = Shellwords.split(ENV["TESTOPTS"] || "")
- end
-
- super
- end
- end
-
- singleton_class.prepend RunRespectingRakeTestopts
-
- # Owes great inspiration to test runner trailblazers like RSpec,
- # minitest-reporters, maxitest and others.
- def self.plugin_rails_init(options)
- ENV["RAILS_ENV"] = options[:environment] || "test"
-
- # 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?
- # 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"]
- # Plugin can run without Rails loaded, check before filtering.
- Minitest.backtrace_filter = ::Rails.backtrace_cleaner if ::Rails.respond_to?(:backtrace_cleaner)
- end
-
- # Replace progress reporter for colors.
- reporter.reporters.delete_if { |reporter| reporter.kind_of?(SummaryReporter) || reporter.kind_of?(ProgressReporter) }
- reporter << SuppressedSummaryReporter.new(options[:io], options)
- reporter << ::Rails::TestUnitReporter.new(options[:io], options)
- end
-
- def self.run_via=(runner)
- if run_via.set?
- raise ArgumentError, "run_via already assigned"
- else
- run_via.runner = runner
- end
- end
-
- class RunVia
- attr_accessor :runner
- alias set? runner
-
- # Backwardscompatibility with Rails 5.0 generated plugin test scripts.
- def []=(runner, *)
- @runner = runner
- end
-
- def ruby?
- runner == :ruby
- end
-
- def rake?
- runner == :rake
- end
- end
-
- mattr_reader :run_via, default: RunVia.new
-end
-
-# Put Rails as the first plugin minitest initializes so other plugins
-# can override or replace our default reporter setup.
-# Since minitest only loads plugins if its extensions are empty we have
-# to call `load_plugins` first.
-Minitest.load_plugins
-Minitest.extensions.unshift "rails"
diff --git a/railties/lib/rails/test_unit/railtie.rb b/railties/lib/rails/test_unit/railtie.rb
index 443e743421..42b6daa3d1 100644
--- a/railties/lib/rails/test_unit/railtie.rb
+++ b/railties/lib/rails/test_unit/railtie.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rails/test_unit/line_filtering"
if defined?(Rake.application) && Rake.application.top_level_tasks.grep(/^(default$|test(:|$))/).any?
diff --git a/railties/lib/rails/test_unit/reporter.rb b/railties/lib/rails/test_unit/reporter.rb
index 1cc27f7b6c..7d3164f1eb 100644
--- a/railties/lib/rails/test_unit/reporter.rb
+++ b/railties/lib/rails/test_unit/reporter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "active_support/core_ext/class/attribute"
require "minitest"
@@ -71,7 +73,12 @@ module Rails
end
def app_root
- @app_root ||= defined?(ENGINE_ROOT) ? ENGINE_ROOT : Rails.root
+ @app_root ||=
+ if defined?(ENGINE_ROOT)
+ ENGINE_ROOT
+ elsif Rails.respond_to?(:root)
+ Rails.root
+ end
end
def colored_output?
diff --git a/railties/lib/rails/test_unit/runner.rb b/railties/lib/rails/test_unit/runner.rb
new file mode 100644
index 0000000000..5c2f6451e2
--- /dev/null
+++ b/railties/lib/rails/test_unit/runner.rb
@@ -0,0 +1,143 @@
+# frozen_string_literal: true
+
+require "shellwords"
+require "method_source"
+require "rake/file_list"
+require "active_support/core_ext/module/attribute_accessors"
+
+module Rails
+ module TestUnit
+ class Runner
+ mattr_reader :filters, default: []
+
+ class << self
+ def attach_before_load_options(opts)
+ opts.on("--warnings", "-w", "Run with Ruby warnings enabled") {}
+ opts.on("--environment", "-e", "Run tests in the ENV environment") {}
+ end
+
+ def parse_options(argv)
+ # Perform manual parsing and cleanup since option parser raises on unknown options.
+ env_index = argv.index("--environment") || argv.index("-e")
+ if env_index
+ argv.delete_at(env_index)
+ environment = argv.delete_at(env_index).strip
+ end
+ ENV["RAILS_ENV"] = environment || "test"
+
+ w_index = argv.index("--warnings") || argv.index("-w")
+ $VERBOSE = argv.delete_at(w_index) if w_index
+ end
+
+ def rake_run(argv = [])
+ ARGV.replace Shellwords.split(ENV["TESTOPTS"] || "")
+
+ run(argv)
+ end
+
+ def run(argv = [])
+ load_tests(argv)
+
+ require "active_support/testing/autorun"
+ end
+
+ def load_tests(argv)
+ patterns = extract_filters(argv)
+
+ tests = Rake::FileList[patterns.any? ? patterns : "test/**/*_test.rb"]
+ tests.exclude("test/system/**/*") if patterns.empty?
+
+ tests.to_a.each { |path| require File.expand_path(path) }
+ end
+
+ def compose_filter(runnable, filter)
+ if filters.any? { |_, lines| lines.any? }
+ CompositeFilter.new(runnable, filter, filters)
+ else
+ filter
+ end
+ end
+
+ private
+ def extract_filters(argv)
+ # Extract absolute and relative paths but skip -n /.*/ regexp filters.
+ argv.select { |arg| arg =~ %r%^/?\w+/% && !arg.end_with?("/") }.map do |path|
+ case
+ when path =~ /(:\d+)+$/
+ file, *lines = path.split(":")
+ filters << [ file, lines ]
+ file
+ when Dir.exist?(path)
+ "#{path}/**/*_test.rb"
+ else
+ filters << [ path, [] ]
+ path
+ end
+ end
+ end
+ end
+ end
+
+ class CompositeFilter # :nodoc:
+ attr_reader :named_filter
+
+ def initialize(runnable, filter, patterns)
+ @runnable = runnable
+ @named_filter = derive_named_filter(filter)
+ @filters = [ @named_filter, *derive_line_filters(patterns) ].compact
+ end
+
+ # Minitest uses === to find matching filters.
+ def ===(method)
+ @filters.any? { |filter| filter === method }
+ end
+
+ private
+ def derive_named_filter(filter)
+ if filter.respond_to?(:named_filter)
+ filter.named_filter
+ elsif filter =~ %r%/(.*)/% # Regexp filtering copied from Minitest.
+ Regexp.new $1
+ elsif filter.is_a?(String)
+ filter
+ end
+ end
+
+ def derive_line_filters(patterns)
+ patterns.flat_map do |file, lines|
+ if lines.empty?
+ Filter.new(@runnable, file, nil) if file
+ else
+ lines.map { |line| Filter.new(@runnable, file, line) }
+ end
+ end
+ end
+ end
+
+ class Filter # :nodoc:
+ def initialize(runnable, file, line)
+ @runnable, @file = runnable, File.expand_path(file)
+ @line = line.to_i if line
+ end
+
+ def ===(method)
+ return unless @runnable.method_defined?(method)
+
+ if @line
+ test_file, test_range = definition_for(@runnable.instance_method(method))
+ test_file == @file && test_range.include?(@line)
+ else
+ @runnable.instance_method(method).source_location.first == @file
+ end
+ end
+
+ private
+ def definition_for(method)
+ file, start_line = method.source_location
+ end_line = method.source.count("\n") + start_line - 1
+
+ return file, start_line..end_line
+ end
+ end
+ end
+end
diff --git a/railties/lib/rails/test_unit/test_requirer.rb b/railties/lib/rails/test_unit/test_requirer.rb
deleted file mode 100644
index 92e5fcf0bc..0000000000
--- a/railties/lib/rails/test_unit/test_requirer.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-require "active_support/core_ext/object/blank"
-require "rake/file_list"
-
-module Rails
- class TestRequirer # :nodoc:
- class << self
- def require_files(patterns, exclude_patterns = [])
- patterns = expand_patterns(patterns)
-
- 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
-
- private
- def expand_patterns(patterns)
- patterns.map do |arg|
- arg = arg.gsub(/(:\d+)+?$/, "")
- if Dir.exist?(arg)
- "#{arg}/**/*_test.rb"
- else
- arg
- end
- end
- end
- end
- end
-end
diff --git a/railties/lib/rails/test_unit/testing.rake b/railties/lib/rails/test_unit/testing.rake
index 33408081f1..32ac27a135 100644
--- a/railties/lib/rails/test_unit/testing.rake
+++ b/railties/lib/rails/test_unit/testing.rake
@@ -1,6 +1,8 @@
+# frozen_string_literal: true
+
gem "minitest"
require "minitest"
-require "rails/test_unit/minitest_plugin"
+require "rails/test_unit/runner"
task default: :test
@@ -9,9 +11,9 @@ task :test do
$: << "test"
if ENV.key?("TEST")
- Minitest.rake_run([ENV["TEST"]])
+ Rails::TestUnit::Runner.rake_run([ENV["TEST"]])
else
- Minitest.rake_run(["test"], ["test/system/**/*"])
+ Rails::TestUnit::Runner.rake_run
end
end
@@ -29,28 +31,28 @@ namespace :test do
["models", "helpers", "controllers", "mailers", "integration", "jobs"].each do |name|
task name => "test:prepare" do
$: << "test"
- Minitest.rake_run(["test/#{name}"])
+ Rails::TestUnit::Runner.rake_run(["test/#{name}"])
end
end
task generators: "test:prepare" do
$: << "test"
- Minitest.rake_run(["test/lib/generators"])
+ Rails::TestUnit::Runner.rake_run(["test/lib/generators"])
end
task units: "test:prepare" do
$: << "test"
- Minitest.rake_run(["test/models", "test/helpers", "test/unit"])
+ Rails::TestUnit::Runner.rake_run(["test/models", "test/helpers", "test/unit"])
end
task functionals: "test:prepare" do
$: << "test"
- Minitest.rake_run(["test/controllers", "test/mailers", "test/functional"])
+ Rails::TestUnit::Runner.rake_run(["test/controllers", "test/mailers", "test/functional"])
end
desc "Run system tests only"
task system: "test:prepare" do
$: << "test"
- Minitest.rake_run(["test/system"])
+ Rails::TestUnit::Runner.rake_run(["test/system"])
end
end
diff --git a/railties/lib/rails/version.rb b/railties/lib/rails/version.rb
index 3d8e8291d1..ba6763a572 100644
--- a/railties/lib/rails/version.rb
+++ b/railties/lib/rails/version.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require_relative "gem_version"
module Rails
diff --git a/railties/lib/rails/welcome_controller.rb b/railties/lib/rails/welcome_controller.rb
index b757dc72ef..5b84b57679 100644
--- a/railties/lib/rails/welcome_controller.rb
+++ b/railties/lib/rails/welcome_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rails/application_controller"
class Rails::WelcomeController < Rails::ApplicationController # :nodoc:
diff --git a/railties/railties.gemspec b/railties/railties.gemspec
index 2df303750c..4c665cd546 100644
--- a/railties/railties.gemspec
+++ b/railties/railties.gemspec
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
version = File.read(File.expand_path("../RAILS_VERSION", __dir__)).strip
Gem::Specification.new do |s|
@@ -23,6 +25,11 @@ Gem::Specification.new do |s|
s.rdoc_options << "--exclude" << "."
+ s.metadata = {
+ "source_code_uri" => "https://github.com/rails/rails/tree/v#{version}/railties",
+ "changelog_uri" => "https://github.com/rails/rails/blob/v#{version}/railties/CHANGELOG.md"
+ }
+
s.add_dependency "activesupport", version
s.add_dependency "actionpack", version
diff --git a/railties/test/abstract_unit.rb b/railties/test/abstract_unit.rb
index 2d4c7a0f0b..b42f37d6b9 100644
--- a/railties/test/abstract_unit.rb
+++ b/railties/test/abstract_unit.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
ENV["RAILS_ENV"] ||= "test"
require "stringio"
@@ -13,7 +15,6 @@ require "rails/all"
module TestApp
class Application < Rails::Application
config.root = __dir__
- secrets.secret_key_base = "b3c631c314c0bbca50c1b2843150fe33"
end
end
diff --git a/railties/test/app_loader_test.rb b/railties/test/app_loader_test.rb
index 85f5502b4d..bb556f1968 100644
--- a/railties/test/app_loader_test.rb
+++ b/railties/test/app_loader_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "tmpdir"
require "abstract_unit"
require "rails/app_loader"
diff --git a/railties/test/application/asset_debugging_test.rb b/railties/test/application/asset_debugging_test.rb
index 3e17a1efa5..e56c7b958e 100644
--- a/railties/test/application/asset_debugging_test.rb
+++ b/railties/test/application/asset_debugging_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
require "rack/test"
@@ -7,10 +9,7 @@ module ApplicationTests
include Rack::Test::Methods
def setup
- # FIXME: shush Sass warning spam, not relevant to testing Railties
- Kernel.silence_warnings do
- build_app(initializers: true)
- end
+ build_app(initializers: true)
app_file "app/assets/javascripts/application.js", "//= require_tree ."
app_file "app/assets/javascripts/xmlhr.js", "function f1() { alert(); }"
@@ -34,16 +33,10 @@ module ApplicationTests
teardown_app
end
- # FIXME: shush Sass warning spam, not relevant to testing Railties
- def get(*)
- Kernel.silence_warnings { super }
- end
-
test "assets are concatenated when debug is off and compile is off either if debug_assets param is provided" do
# config.assets.debug and config.assets.compile are false for production environment
ENV["RAILS_ENV"] = "production"
- output = Dir.chdir(app_path) { `bin/rails assets:precompile --trace 2>&1` }
- assert $?.success?, output
+ rails "assets:precompile", "--trace"
# Load app env
app "production"
diff --git a/railties/test/application/assets_test.rb b/railties/test/application/assets_test.rb
index f38cacd6da..0d3262d6f6 100644
--- a/railties/test/application/assets_test.rb
+++ b/railties/test/application/assets_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
require "rack/test"
require "active_support/json"
@@ -60,10 +62,7 @@ module ApplicationTests
add_to_env_config "development", "config.assets.digest = false"
- # FIXME: shush Sass warning spam, not relevant to testing Railties
- Kernel.silence_warnings do
- require "#{app_path}/config/environment"
- end
+ require "#{app_path}/config/environment"
get "/assets/demo.js"
assert_equal 'a = "/assets/rails.png";', last_response.body.strip
@@ -475,9 +474,9 @@ module ApplicationTests
class ::PostsController < ActionController::Base; end
- get "/posts", {}, "HTTPS" => "off"
+ get "/posts", {}, { "HTTPS" => "off" }
assert_match('src="http://example.com/assets/application.self.js', last_response.body)
- get "/posts", {}, "HTTPS" => "on"
+ get "/posts", {}, { "HTTPS" => "on" }
assert_match('src="https://example.com/assets/application.self.js', last_response.body)
end
diff --git a/railties/test/application/bin_setup_test.rb b/railties/test/application/bin_setup_test.rb
index 0fb995900f..54934dbe24 100644
--- a/railties/test/application/bin_setup_test.rb
+++ b/railties/test/application/bin_setup_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
module ApplicationTests
@@ -20,7 +22,7 @@ module ApplicationTests
end
RUBY
- list_tables = lambda { `bin/rails runner 'p ActiveRecord::Base.connection.tables'`.strip }
+ list_tables = lambda { rails("runner", "p ActiveRecord::Base.connection.tables").strip }
File.write("log/test.log", "zomg!")
assert_equal "[]", list_tables.call
diff --git a/railties/test/application/configuration/custom_test.rb b/railties/test/application/configuration/custom_test.rb
index 8360b7bf4b..05b17b4a7a 100644
--- a/railties/test/application/configuration/custom_test.rb
+++ b/railties/test/application/configuration/custom_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
module ApplicationTests
diff --git a/railties/test/application/configuration_test.rb b/railties/test/application/configuration_test.rb
index 06767167a9..bb8cc0876c 100644
--- a/railties/test/application/configuration_test.rb
+++ b/railties/test/application/configuration_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
require "rack/test"
require "env_helpers"
@@ -38,10 +40,7 @@ module ApplicationTests
@app ||= begin
ENV["RAILS_ENV"] = env
- # FIXME: shush Sass warning spam, not relevant to testing Railties
- Kernel.silence_warnings do
- require "#{app_path}/config/environment"
- end
+ require "#{app_path}/config/environment"
Rails.application
ensure
@@ -176,13 +175,11 @@ module ApplicationTests
test "Rails.application responds to all instance methods" do
app "development"
- assert_respond_to Rails.application, :routes_reloader
assert_equal Rails.application.routes_reloader, AppTemplate::Application.routes_reloader
end
test "Rails::Application responds to paths" do
app "development"
- assert_respond_to AppTemplate::Application, :paths
assert_equal ["#{app_path}/app/views"], AppTemplate::Application.paths["app/views"].expanded
end
@@ -240,6 +237,66 @@ module ApplicationTests
assert_instance_of Pathname, Rails.public_path
end
+ test "does not eager load controller actions in development" do
+ app_file "app/controllers/posts_controller.rb", <<-RUBY
+ class PostsController < ActionController::Base
+ def index;end
+ def show;end
+ end
+ RUBY
+
+ app "development"
+
+ assert_nil PostsController.instance_variable_get(:@action_methods)
+ end
+
+ test "eager loads controller actions in production" do
+ app_file "app/controllers/posts_controller.rb", <<-RUBY
+ class PostsController < ActionController::Base
+ def index;end
+ def show;end
+ end
+ RUBY
+
+ add_to_config <<-RUBY
+ config.eager_load = true
+ config.cache_classes = true
+ RUBY
+
+ app "production"
+
+ assert_equal %w(index show).to_set, PostsController.instance_variable_get(:@action_methods)
+ end
+
+ test "does not eager load mailer actions in development" do
+ app_file "app/mailers/posts_mailer.rb", <<-RUBY
+ class PostsMailer < ActionMailer::Base
+ def noop_email;end
+ end
+ RUBY
+
+ app "development"
+
+ assert_nil PostsMailer.instance_variable_get(:@action_methods)
+ end
+
+ test "eager loads mailer actions in production" do
+ app_file "app/mailers/posts_mailer.rb", <<-RUBY
+ class PostsMailer < ActionMailer::Base
+ def noop_email;end
+ end
+ RUBY
+
+ add_to_config <<-RUBY
+ config.eager_load = true
+ config.cache_classes = true
+ RUBY
+
+ app "production"
+
+ assert_equal %w(noop_email).to_set, PostsMailer.instance_variable_get(:@action_methods)
+ end
+
test "initialize an eager loaded, cache classes app" do
add_to_config <<-RUBY
config.eager_load = true
@@ -257,6 +314,7 @@ module ApplicationTests
end
test "the application can be eager loaded even when there are no frameworks" do
+ FileUtils.rm_rf("#{app_path}/app/jobs/application_job.rb")
FileUtils.rm_rf("#{app_path}/app/models/application_record.rb")
FileUtils.rm_rf("#{app_path}/app/mailers/application_mailer.rb")
FileUtils.rm_rf("#{app_path}/config/environments")
@@ -418,47 +476,61 @@ module ApplicationTests
test "application message verifier can be used when the key_generator is ActiveSupport::LegacyKeyGenerator" do
app_file "config/initializers/secret_token.rb", <<-RUBY
+ Rails.application.credentials.secret_key_base = nil
Rails.application.config.secret_token = "b3c631c314c0bbca50c1b2843150fe33"
RUBY
- app_file "config/secrets.yml", <<-YAML
- development:
- secret_key_base:
- YAML
- app "development"
+ app "production"
- assert_equal app.env_config["action_dispatch.key_generator"], Rails.application.key_generator
- assert_equal app.env_config["action_dispatch.key_generator"].class, ActiveSupport::LegacyKeyGenerator
+ assert_kind_of ActiveSupport::LegacyKeyGenerator, Rails.application.key_generator
message = app.message_verifier(:sensitive_value).generate("some_value")
assert_equal "some_value", Rails.application.message_verifier(:sensitive_value).verify(message)
end
- test "warns when secrets.secret_key_base is blank and config.secret_token is set" do
+ test "config.secret_token is deprecated" do
app_file "config/initializers/secret_token.rb", <<-RUBY
Rails.application.config.secret_token = "b3c631c314c0bbca50c1b2843150fe33"
RUBY
- app_file "config/secrets.yml", <<-YAML
- development:
- secret_key_base:
- YAML
- app "development"
+ app "production"
- assert_deprecated(/You didn't set `secret_key_base`./) do
- app.env_config
+ assert_deprecated(/secret_token/) do
+ app.secrets
end
end
- test "raise when secrets.secret_key_base is not a type of string" do
+ test "secrets.secret_token is deprecated" do
app_file "config/secrets.yml", <<-YAML
- development:
- secret_key_base: 123
+ production:
+ secret_token: "b3c631c314c0bbca50c1b2843150fe33"
YAML
- app "development"
+ app "production"
+
+ assert_deprecated(/secret_token/) do
+ app.secrets
+ end
+ end
+
+
+ test "raises when secret_key_base is blank" do
+ app_file "config/initializers/secret_token.rb", <<-RUBY
+ Rails.application.credentials.secret_key_base = nil
+ RUBY
+
+ error = assert_raise(ArgumentError) do
+ app "production"
+ end
+ assert_match(/Missing `secret_key_base`./, error.message)
+ end
+
+ test "raise when secret_key_base is not a type of string" do
+ add_to_config <<-RUBY
+ Rails.application.credentials.secret_key_base = 123
+ RUBY
assert_raise(ArgumentError) do
- app.key_generator
+ app "production"
end
end
@@ -478,7 +550,7 @@ module ApplicationTests
test "application verifier can build different verifiers" do
make_basic_app do |application|
- application.secrets.secret_key_base = "b3c631c314c0bbca50c1b2843150fe33"
+ application.credentials.secret_key_base = "b3c631c314c0bbca50c1b2843150fe33"
application.config.session_store :disabled
end
@@ -596,37 +668,15 @@ module ApplicationTests
test "uses ActiveSupport::LegacyKeyGenerator as app.key_generator when secrets.secret_key_base is blank" do
app_file "config/initializers/secret_token.rb", <<-RUBY
+ Rails.application.credentials.secret_key_base = nil
Rails.application.config.secret_token = "b3c631c314c0bbca50c1b2843150fe33"
RUBY
- app_file "config/secrets.yml", <<-YAML
- development:
- secret_key_base:
- YAML
- app "development"
+ app "production"
assert_equal "b3c631c314c0bbca50c1b2843150fe33", app.config.secret_token
- assert_nil app.secrets.secret_key_base
- assert_equal app.key_generator.class, ActiveSupport::LegacyKeyGenerator
- end
-
- test "uses ActiveSupport::LegacyKeyGenerator with config.secret_token as app.key_generator when secrets.secret_key_base is blank" do
- app_file "config/initializers/secret_token.rb", <<-RUBY
- Rails.application.config.secret_token = ""
- RUBY
- app_file "config/secrets.yml", <<-YAML
- development:
- secret_key_base:
- YAML
-
- app "development"
-
- assert_equal "", app.config.secret_token
- assert_nil app.secrets.secret_key_base
- e = assert_raise ArgumentError do
- app.key_generator
- end
- assert_match(/\AA secret is required/, e.message)
+ assert_nil app.credentials.secret_key_base
+ assert_kind_of ActiveSupport::LegacyKeyGenerator, app.key_generator
end
test "that nested keys are symbolized the same as parents for hashes more than one level deep" do
@@ -643,6 +693,20 @@ module ApplicationTests
assert_equal "697361616320736c6f616e2028656c6f7265737429", app.secrets.smtp_settings[:password]
end
+ test "require_master_key aborts app boot when missing key" do
+ skip "can't run without fork" unless Process.respond_to?(:fork)
+
+ remove_file "config/master.key"
+ add_to_config "config.require_master_key = true"
+
+ error = capture(:stderr) do
+ Process.wait(Process.fork { app "development" })
+ end
+
+ assert_equal 1, $?.exitstatus
+ assert_match(/Missing.*RAILS_MASTER_KEY/, error)
+ end
+
test "protect from forgery is the default in a new app" do
make_basic_app
@@ -1132,6 +1196,9 @@ module ApplicationTests
app "development"
+ force_lazy_load_hooks { ActionController::Base }
+ force_lazy_load_hooks { ActionController::API }
+
assert_equal :raise, ActionController::Parameters.action_on_unpermitted_parameters
post "/posts", post: { "title" => "zomg" }
@@ -1140,6 +1207,10 @@ module ApplicationTests
test "config.action_controller.always_permitted_parameters are: controller, action by default" do
app "development"
+
+ force_lazy_load_hooks { ActionController::Base }
+ force_lazy_load_hooks { ActionController::API }
+
assert_equal %w(controller action), ActionController::Parameters.always_permitted_parameters
end
@@ -1150,6 +1221,9 @@ module ApplicationTests
app "development"
+ force_lazy_load_hooks { ActionController::Base }
+ force_lazy_load_hooks { ActionController::API }
+
assert_equal %w( controller action format ), ActionController::Parameters.always_permitted_parameters
end
@@ -1172,6 +1246,9 @@ module ApplicationTests
app "development"
+ force_lazy_load_hooks { ActionController::Base }
+ force_lazy_load_hooks { ActionController::API }
+
assert_equal :raise, ActionController::Parameters.action_on_unpermitted_parameters
post "/posts", post: { "title" => "zomg" }, format: "json"
@@ -1181,21 +1258,73 @@ module ApplicationTests
test "config.action_controller.action_on_unpermitted_parameters is :log by default on development" do
app "development"
+ force_lazy_load_hooks { ActionController::Base }
+ force_lazy_load_hooks { ActionController::API }
+
assert_equal :log, ActionController::Parameters.action_on_unpermitted_parameters
end
test "config.action_controller.action_on_unpermitted_parameters is :log by default on test" do
app "test"
+ force_lazy_load_hooks { ActionController::Base }
+ force_lazy_load_hooks { ActionController::API }
+
assert_equal :log, ActionController::Parameters.action_on_unpermitted_parameters
end
test "config.action_controller.action_on_unpermitted_parameters is false by default on production" do
app "production"
+ force_lazy_load_hooks { ActionController::Base }
+ force_lazy_load_hooks { ActionController::API }
+
assert_equal false, ActionController::Parameters.action_on_unpermitted_parameters
end
+ test "config.action_controller.default_protect_from_forgery is true by default" do
+ app "development"
+
+ assert_equal true, ActionController::Base.default_protect_from_forgery
+ assert_includes ActionController::Base.__callbacks[:process_action].map(&:filter), :verify_authenticity_token
+ end
+
+ test "config.action_controller.permit_all_parameters can be configured in an initializer" do
+ app_file "config/initializers/permit_all_parameters.rb", <<-RUBY
+ Rails.application.config.action_controller.permit_all_parameters = true
+ RUBY
+
+ app "development"
+
+ force_lazy_load_hooks { ActionController::Base }
+ force_lazy_load_hooks { ActionController::API }
+ assert_equal true, ActionController::Parameters.permit_all_parameters
+ end
+
+ test "config.action_controller.always_permitted_parameters can be configured in an initializer" do
+ app_file "config/initializers/always_permitted_parameters.rb", <<-RUBY
+ Rails.application.config.action_controller.always_permitted_parameters = []
+ RUBY
+
+ app "development"
+
+ force_lazy_load_hooks { ActionController::Base }
+ force_lazy_load_hooks { ActionController::API }
+ assert_equal [], ActionController::Parameters.always_permitted_parameters
+ end
+
+ test "config.action_controller.action_on_unpermitted_parameters can be configured in an initializer" do
+ app_file "config/initializers/action_on_unpermitted_parameters.rb", <<-RUBY
+ Rails.application.config.action_controller.action_on_unpermitted_parameters = :raise
+ RUBY
+
+ app "development"
+
+ force_lazy_load_hooks { ActionController::Base }
+ force_lazy_load_hooks { ActionController::API }
+ assert_equal :raise, ActionController::Parameters.action_on_unpermitted_parameters
+ end
+
test "config.action_dispatch.ignore_accept_header" do
make_basic_app do |application|
application.config.action_dispatch.ignore_accept_header = true
@@ -1210,17 +1339,16 @@ module ApplicationTests
end
end
- get "/", {}, "HTTP_ACCEPT" => "application/xml"
+ get "/", {}, { "HTTP_ACCEPT" => "application/xml" }
assert_equal "HTML", last_response.body
- get "/", { format: :xml }, "HTTP_ACCEPT" => "application/xml"
+ get "/", { format: :xml }, { "HTTP_ACCEPT" => "application/xml" }
assert_equal "XML", last_response.body
end
test "Rails.application#env_config exists and include some existing parameters" do
make_basic_app
- assert_respond_to app, :env_config
assert_equal app.env_config["action_dispatch.parameter_filter"], app.config.filter_parameters
assert_equal app.env_config["action_dispatch.show_exceptions"], app.config.action_dispatch.show_exceptions
assert_equal app.env_config["action_dispatch.logger"], Rails.logger
@@ -1400,8 +1528,8 @@ module ApplicationTests
test "raises with proper error message if no database configuration found" do
FileUtils.rm("#{app_path}/config/database.yml")
- app "development"
err = assert_raises RuntimeError do
+ app "development"
Rails.application.config.database_configuration
end
assert_match "config/database", err.message
@@ -1533,6 +1661,52 @@ module ApplicationTests
assert_equal({}, Rails.application.config.my_custom_config)
end
+ test "default SQLite3Adapter.represent_boolean_as_integer for 5.1 is false" do
+ remove_from_config '.*config\.load_defaults.*\n'
+ add_to_top_of_config <<-RUBY
+ config.load_defaults 5.1
+ RUBY
+ app_file "app/models/post.rb", <<-RUBY
+ class Post < ActiveRecord::Base
+ end
+ RUBY
+
+ app "development"
+ force_lazy_load_hooks { Post }
+
+ assert_not ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer
+ end
+
+ test "default SQLite3Adapter.represent_boolean_as_integer for new installs is true" do
+ app_file "app/models/post.rb", <<-RUBY
+ class Post < ActiveRecord::Base
+ end
+ RUBY
+
+ app "development"
+ force_lazy_load_hooks { Post }
+
+ assert ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer
+ end
+
+ test "represent_boolean_as_integer should be able to set via config.active_record.sqlite3.represent_boolean_as_integer" do
+ remove_from_config '.*config\.load_defaults.*\n'
+
+ app_file "config/initializers/new_framework_defaults_5_2.rb", <<-RUBY
+ Rails.application.config.active_record.sqlite3.represent_boolean_as_integer = true
+ RUBY
+
+ app_file "app/models/post.rb", <<-RUBY
+ class Post < ActiveRecord::Base
+ end
+ RUBY
+
+ app "development"
+ force_lazy_load_hooks { Post }
+
+ assert ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer
+ end
+
test "config_for containing ERB tags should evaluate" do
app_file "config/custom.yml", <<-RUBY
development:
@@ -1639,5 +1813,10 @@ module ApplicationTests
assert_equal 301, last_response.status
assert_equal "https://example.org/", last_response.location
end
+
+ private
+ def force_lazy_load_hooks
+ yield # Tasty clarifying sugar, homie! We only need to reference a constant to load it.
+ end
end
end
diff --git a/railties/test/application/console_test.rb b/railties/test/application/console_test.rb
index 057d473870..13164f49c2 100644
--- a/railties/test/application/console_test.rb
+++ b/railties/test/application/console_test.rb
@@ -1,4 +1,7 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
+require "console_helpers"
class ConsoleTest < ActiveSupport::TestCase
include ActiveSupport::Testing::Isolation
@@ -93,14 +96,11 @@ class ConsoleTest < ActiveSupport::TestCase
end
end
-begin
- require "pty"
-rescue LoadError
-end
-
class FullStackConsoleTest < ActiveSupport::TestCase
+ include ConsoleHelpers
+
def setup
- skip "PTY unavailable" unless defined?(PTY) && PTY.respond_to?(:open)
+ skip "PTY unavailable" unless available_pty?
build_app
app_file "app/models/post.rb", <<-CODE
@@ -116,24 +116,11 @@ class FullStackConsoleTest < ActiveSupport::TestCase
teardown_app
end
- def assert_output(expected, timeout = 1)
- timeout = Time.now + timeout
-
- output = ""
- until output.include?(expected) || Time.now > timeout
- if IO.select([@master], [], [], 0.1)
- output << @master.read(1)
- end
- end
-
- assert_includes output, expected, "#{expected.inspect} expected, but got:\n\n#{output}"
- end
-
def write_prompt(command, expected_output = nil)
@master.puts command
- assert_output command
- assert_output expected_output if expected_output
- assert_output "> "
+ assert_output command, @master
+ assert_output expected_output, @master if expected_output
+ assert_output "> ", @master
end
def spawn_console(options)
@@ -142,7 +129,7 @@ class FullStackConsoleTest < ActiveSupport::TestCase
in: @slave, out: @slave, err: @slave
)
- assert_output "> ", 30
+ assert_output "> ", @master, 30
end
def test_sandbox
diff --git a/railties/test/application/current_attributes_integration_test.rb b/railties/test/application/current_attributes_integration_test.rb
index 5653ec0be1..146e96facc 100644
--- a/railties/test/application/current_attributes_integration_test.rb
+++ b/railties/test/application/current_attributes_integration_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
require "rack/test"
@@ -37,6 +39,8 @@ class CurrentAttributesIntegrationTest < ActiveSupport::TestCase
app_file "app/controllers/customers_controller.rb", <<-RUBY
class CustomersController < ApplicationController
+ layout false
+
def set_current_customer
Current.customer = Customer.new("david")
render :index
diff --git a/railties/test/application/dbconsole_test.rb b/railties/test/application/dbconsole_test.rb
new file mode 100644
index 0000000000..8eb293c179
--- /dev/null
+++ b/railties/test/application/dbconsole_test.rb
@@ -0,0 +1,74 @@
+# frozen_string_literal: true
+
+require "isolation/abstract_unit"
+require "console_helpers"
+
+module ApplicationTests
+ class DBConsoleTest < ActiveSupport::TestCase
+ include ActiveSupport::Testing::Isolation
+ include ConsoleHelpers
+
+ def setup
+ skip "PTY unavailable" unless available_pty?
+
+ build_app
+ end
+
+ def teardown
+ teardown_app
+ end
+
+ def test_use_value_defined_in_environment_file_in_database_yml
+ app_file "config/database.yml", <<-YAML
+ development:
+ database: <%= Rails.application.config.database %>
+ adapter: sqlite3
+ pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
+ timeout: 5000
+ YAML
+
+ app_file "config/environments/development.rb", <<-RUBY
+ Rails.application.configure do
+ config.database = "db/development.sqlite3"
+ end
+ RUBY
+
+ master, slave = PTY.open
+ spawn_dbconsole(slave)
+ assert_output("sqlite>", master)
+ ensure
+ master.puts ".exit"
+ end
+
+ def test_respect_environment_option
+ app_file "config/database.yml", <<-YAML
+ default: &default
+ adapter: sqlite3
+ pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
+ timeout: 5000
+
+ development:
+ <<: *default
+ database: db/development.sqlite3
+
+ production:
+ <<: *default
+ database: db/production.sqlite3
+ YAML
+
+ master, slave = PTY.open
+ spawn_dbconsole(slave, "-e production")
+ assert_output("sqlite>", master)
+
+ master.puts "pragma database_list;"
+ assert_output("production.sqlite3", master)
+ ensure
+ master.puts ".exit"
+ end
+
+ private
+ def spawn_dbconsole(fd, options = nil)
+ Process.spawn("#{app_path}/bin/rails dbconsole #{options}", in: fd, out: fd, err: fd)
+ end
+ end
+end
diff --git a/railties/test/application/generators_test.rb b/railties/test/application/generators_test.rb
index fe581db286..e5e557d204 100644
--- a/railties/test/application/generators_test.rb
+++ b/railties/test/application/generators_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
module ApplicationTests
@@ -29,7 +31,7 @@ module ApplicationTests
end
test "allow running plugin new generator inside Rails app directory" do
- FileUtils.cd(rails_root) { `ruby bin/rails plugin new vendor/plugins/bukkits` }
+ rails "plugin", "new", "vendor/plugins/bukkits"
assert File.exist?(File.join(rails_root, "vendor/plugins/bukkits/test/dummy/config/application.rb"))
end
@@ -165,13 +167,14 @@ module ApplicationTests
config.api_only = true
RUBY
- FileUtils.cd(rails_root) { `bin/rails generate mailer notifier foo` }
+ rails "generate", "mailer", "notifier", "foo"
assert File.exist?(File.join(rails_root, "app/views/notifier_mailer/foo.text.erb"))
assert File.exist?(File.join(rails_root, "app/views/notifier_mailer/foo.html.erb"))
end
test "ARGV is mutated as expected" do
require "#{app_path}/config/environment"
+ require "rails/command"
Rails::Command.const_set("APP_PATH", "rails/all")
FileUtils.cd(rails_root) do
@@ -185,12 +188,13 @@ module ApplicationTests
Rails::Command.send(:remove_const, "APP_PATH")
end
- test "help does not show hidden namespaces" do
+ test "help does not show hidden namespaces and hidden commands" do
FileUtils.cd(rails_root) do
- output = `bin/rails generate --help`
+ output = rails("generate", "--help")
assert_no_match "active_record:migration", output
+ assert_no_match "credentials", output
- output = `bin/rails destroy --help`
+ output = rails("destroy", "--help")
assert_no_match "active_record:migration", output
end
end
diff --git a/railties/test/application/help_test.rb b/railties/test/application/help_test.rb
index 0c3fe8bfa3..f728fc3b85 100644
--- a/railties/test/application/help_test.rb
+++ b/railties/test/application/help_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
class HelpTest < ActiveSupport::TestCase
@@ -12,12 +14,12 @@ class HelpTest < ActiveSupport::TestCase
end
test "command works" do
- output = Dir.chdir(app_path) { `bin/rails help` }
+ output = rails("help")
assert_match "The most common rails commands are", output
end
test "short-cut alias works" do
- output = Dir.chdir(app_path) { `bin/rails -h` }
+ output = rails("-h")
assert_match "The most common rails commands are", output
end
end
diff --git a/railties/test/application/initializers/frameworks_test.rb b/railties/test/application/initializers/frameworks_test.rb
index eb2c578f91..d2b77bd015 100644
--- a/railties/test/application/initializers/frameworks_test.rb
+++ b/railties/test/application/initializers/frameworks_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
module ApplicationTests
@@ -209,24 +211,20 @@ module ApplicationTests
test "database middleware doesn't initialize when activerecord is not in frameworks" do
use_frameworks []
require "#{app_path}/config/environment"
- assert_nil defined?(ActiveRecord::Base)
+ assert !defined?(ActiveRecord::Base) || ActiveRecord.autoload?(:Base)
end
test "use schema cache dump" do
- Dir.chdir(app_path) do
- `rails generate model post title:string;
- bin/rails db:migrate db:schema:cache:dump`
- end
+ rails %w(generate model post title:string)
+ rails %w(db:migrate db:schema:cache:dump)
require "#{app_path}/config/environment"
ActiveRecord::Base.connection.drop_table("posts") # force drop posts table for test.
assert ActiveRecord::Base.connection.schema_cache.data_sources("posts")
end
test "expire schema cache dump" do
- Dir.chdir(app_path) do
- `rails generate model post title:string;
- bin/rails db:migrate db:schema:cache:dump db:rollback`
- end
+ rails %w(generate model post title:string)
+ rails %w(db:migrate db:schema:cache:dump db:rollback)
require "#{app_path}/config/environment"
assert !ActiveRecord::Base.connection.schema_cache.data_sources("posts")
end
diff --git a/railties/test/application/initializers/hooks_test.rb b/railties/test/application/initializers/hooks_test.rb
index 36926c50ff..1e130c2f9e 100644
--- a/railties/test/application/initializers/hooks_test.rb
+++ b/railties/test/application/initializers/hooks_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
module ApplicationTests
diff --git a/railties/test/application/initializers/i18n_test.rb b/railties/test/application/initializers/i18n_test.rb
index 206e42703b..8058052771 100644
--- a/railties/test/application/initializers/i18n_test.rb
+++ b/railties/test/application/initializers/i18n_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
module ApplicationTests
@@ -245,7 +247,7 @@ fr:
end
test "[shortcut] config.i18n.fallbacks = [{ :ca => :'es-ES' }] initializes fallbacks with a mapping ca => es-ES" do
- I18n::Railtie.config.i18n.fallbacks.map = { ca: :'es-ES' }
+ I18n::Railtie.config.i18n.fallbacks = [{ ca: :'es-ES' }]
load_app
assert_fallbacks ca: [:ca, :"es-ES", :es, :en]
end
diff --git a/railties/test/application/initializers/load_path_test.rb b/railties/test/application/initializers/load_path_test.rb
index dbefb22837..78cd4776d6 100644
--- a/railties/test/application/initializers/load_path_test.rb
+++ b/railties/test/application/initializers/load_path_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
module ApplicationTests
diff --git a/railties/test/application/initializers/notifications_test.rb b/railties/test/application/initializers/notifications_test.rb
index b847ac6b36..23b20d578c 100644
--- a/railties/test/application/initializers/notifications_test.rb
+++ b/railties/test/application/initializers/notifications_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
module ApplicationTests
diff --git a/railties/test/application/integration_test_case_test.rb b/railties/test/application/integration_test_case_test.rb
index 1118e5037a..c08761092b 100644
--- a/railties/test/application/integration_test_case_test.rb
+++ b/railties/test/application/integration_test_case_test.rb
@@ -1,8 +1,11 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
+require "env_helpers"
module ApplicationTests
class IntegrationTestCaseTest < ActiveSupport::TestCase
- include ActiveSupport::Testing::Isolation
+ include ActiveSupport::Testing::Isolation, EnvHelpers
setup do
build_app
@@ -13,7 +16,7 @@ module ApplicationTests
end
test "resets Action Mailer test deliveries" do
- script("generate mailer BaseMailer welcome")
+ rails "generate", "mailer", "BaseMailer", "welcome"
app_file "test/integration/mailer_integration_test.rb", <<-RUBY
require 'test_helper'
@@ -37,14 +40,14 @@ module ApplicationTests
end
RUBY
- output = Dir.chdir(app_path) { `bin/rails test 2>&1` }
- assert_equal 0, $?.to_i, output
+ with_rails_env("test") { rails("db:migrate") }
+ output = rails("test")
assert_match(/0 failures, 0 errors/, output)
end
end
class IntegrationTestDefaultApp < ActiveSupport::TestCase
- include ActiveSupport::Testing::Isolation
+ include ActiveSupport::Testing::Isolation, EnvHelpers
setup do
build_app
@@ -65,8 +68,8 @@ module ApplicationTests
end
RUBY
- output = Dir.chdir(app_path) { `bin/rails test 2>&1` }
- assert_equal 0, $?.to_i, output
+ with_rails_env("test") { rails("db:migrate") }
+ output = rails("test")
assert_match(/0 failures, 0 errors/, output)
end
end
diff --git a/railties/test/application/loading_test.rb b/railties/test/application/loading_test.rb
index c75a25bc6f..de1e240fd3 100644
--- a/railties/test/application/loading_test.rb
+++ b/railties/test/application/loading_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
class LoadingTest < ActiveSupport::TestCase
@@ -115,11 +117,11 @@ class LoadingTest < ActiveSupport::TestCase
require "#{rails_root}/config/environment"
setup_ar!
- assert_equal [ActiveRecord::SchemaMigration, ActiveRecord::InternalMetadata], ActiveRecord::Base.descendants
+ assert_equal [ActiveStorage::Blob, ActiveStorage::Attachment, ActiveRecord::SchemaMigration, ActiveRecord::InternalMetadata].collect(&:to_s).sort, ActiveRecord::Base.descendants.collect(&:to_s).sort
get "/load"
- assert_equal [ActiveRecord::SchemaMigration, ActiveRecord::InternalMetadata, Post], ActiveRecord::Base.descendants
+ assert_equal [ActiveStorage::Blob, ActiveStorage::Attachment, ActiveRecord::SchemaMigration, ActiveRecord::InternalMetadata, Post].collect(&:to_s).sort, ActiveRecord::Base.descendants.collect(&:to_s).sort
get "/unload"
- assert_equal [ActiveRecord::SchemaMigration, ActiveRecord::InternalMetadata], ActiveRecord::Base.descendants
+ assert_equal [ActiveStorage::Blob, ActiveStorage::Attachment, ActiveRecord::SchemaMigration, ActiveRecord::InternalMetadata].collect(&:to_s).sort, ActiveRecord::Base.descendants.collect(&:to_s).sort
end
test "initialize cant be called twice" do
@@ -298,7 +300,7 @@ class LoadingTest < ActiveSupport::TestCase
end
MIGRATION
- Dir.chdir(app_path) { `rake db:migrate` }
+ rails("db:migrate")
require "#{rails_root}/config/environment"
get "/title"
@@ -312,7 +314,7 @@ class LoadingTest < ActiveSupport::TestCase
end
MIGRATION
- Dir.chdir(app_path) { `rake db:migrate` }
+ rails("db:migrate")
get "/body"
assert_equal "BODY", last_response.body
diff --git a/railties/test/application/mailer_previews_test.rb b/railties/test/application/mailer_previews_test.rb
index f5c013dab6..4e77cece1b 100644
--- a/railties/test/application/mailer_previews_test.rb
+++ b/railties/test/application/mailer_previews_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
require "rack/test"
require "base64"
@@ -30,7 +32,7 @@ module ApplicationTests
test "/rails/mailers is accessible with correct configuration" do
add_to_config "config.action_mailer.show_previews = true"
app("production")
- get "/rails/mailers", {}, "REMOTE_ADDR" => "4.2.42.42"
+ get "/rails/mailers", {}, { "REMOTE_ADDR" => "4.2.42.42" }
assert_equal 200, last_response.status
end
@@ -480,7 +482,7 @@ module ApplicationTests
app("development")
- get "/rails/mailers", {}, "SCRIPT_NAME" => "/my_app"
+ get "/rails/mailers", {}, { "SCRIPT_NAME" => "/my_app" }
assert_match '<h3><a href="/my_app/rails/mailers/notifier">Notifier</a></h3>', last_response.body
assert_match '<li><a href="/my_app/rails/mailers/notifier/foo">foo</a></li>', last_response.body
end
diff --git a/railties/test/application/middleware/cache_test.rb b/railties/test/application/middleware/cache_test.rb
index 93b5263bf7..9822ec563d 100644
--- a/railties/test/application/middleware/cache_test.rb
+++ b/railties/test/application/middleware/cache_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
module ApplicationTests
@@ -54,7 +56,7 @@ module ApplicationTests
simple_controller
expected = "Wed, 30 May 1984 19:43:31 GMT"
- get "/expires/keeps_if_modified_since", {}, "HTTP_IF_MODIFIED_SINCE" => expected
+ get "/expires/keeps_if_modified_since", {}, { "HTTP_IF_MODIFIED_SINCE" => expected }
assert_equal 200, last_response.status
assert_equal expected, last_response.body, "cache should have kept If-Modified-Since"
@@ -119,7 +121,7 @@ module ApplicationTests
etag = last_response.headers["ETag"]
- get "/expires/expires_etag", {}, "HTTP_IF_NONE_MATCH" => etag
+ get "/expires/expires_etag", {}, { "HTTP_IF_NONE_MATCH" => etag }
assert_equal "stale, valid, store", last_response.headers["X-Rack-Cache"]
assert_equal 304, last_response.status
assert_equal "", last_response.body
@@ -137,7 +139,7 @@ module ApplicationTests
body = last_response.body
etag = last_response.headers["ETag"]
- get "/expires/expires_etag", { private: true }, "HTTP_IF_NONE_MATCH" => etag
+ get "/expires/expires_etag", { private: true }, { "HTTP_IF_NONE_MATCH" => etag }
assert_equal "miss", last_response.headers["X-Rack-Cache"]
assert_not_equal body, last_response.body
end
@@ -153,7 +155,7 @@ module ApplicationTests
last = last_response.headers["Last-Modified"]
- get "/expires/expires_last_modified", {}, "HTTP_IF_MODIFIED_SINCE" => last
+ get "/expires/expires_last_modified", {}, { "HTTP_IF_MODIFIED_SINCE" => last }
assert_equal "stale, valid, store", last_response.headers["X-Rack-Cache"]
assert_equal 304, last_response.status
assert_equal "", last_response.body
@@ -171,7 +173,7 @@ module ApplicationTests
body = last_response.body
last = last_response.headers["Last-Modified"]
- get "/expires/expires_last_modified", { private: true }, "HTTP_IF_MODIFIED_SINCE" => last
+ get "/expires/expires_last_modified", { private: true }, { "HTTP_IF_MODIFIED_SINCE" => last }
assert_equal "miss", last_response.headers["X-Rack-Cache"]
assert_not_equal body, last_response.body
end
diff --git a/railties/test/application/middleware/cookies_test.rb b/railties/test/application/middleware/cookies_test.rb
index 1e4b5d086c..ecb4ee3446 100644
--- a/railties/test/application/middleware/cookies_test.rb
+++ b/railties/test/application/middleware/cookies_test.rb
@@ -1,8 +1,12 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
+require "rack/test"
module ApplicationTests
class CookiesTest < ActiveSupport::TestCase
include ActiveSupport::Testing::Isolation
+ include Rack::Test::Methods
def new_app
File.expand_path("#{app_path}/../new_app")
@@ -13,6 +17,10 @@ module ApplicationTests
FileUtils.rm_rf("#{app_path}/config/environments")
end
+ def app
+ Rails.application
+ end
+
def teardown
teardown_app
FileUtils.rm_rf(new_app) if File.directory?(new_app)
@@ -42,5 +50,144 @@ module ApplicationTests
require "#{app_path}/config/environment"
assert_equal false, ActionDispatch::Cookies::CookieJar.always_write_cookie
end
+
+ test "signed cookies with SHA512 digest and rotated out SHA256 and SHA1 digests" do
+ app_file "config/routes.rb", <<-RUBY
+ Rails.application.routes.draw do
+ get ':controller(/:action)'
+ post ':controller(/:action)'
+ end
+ RUBY
+
+ controller :foo, <<-RUBY
+ class FooController < ActionController::Base
+ protect_from_forgery with: :null_session
+
+ def write_raw_cookie_sha1
+ cookies[:signed_cookie] = TestVerifiers.sha1.generate("signed cookie")
+ head :ok
+ end
+
+ def write_raw_cookie_sha256
+ cookies[:signed_cookie] = TestVerifiers.sha256.generate("signed cookie")
+ head :ok
+ end
+
+ def read_signed
+ render plain: cookies.signed[:signed_cookie].inspect
+ end
+
+ def read_raw_cookie
+ render plain: cookies[:signed_cookie]
+ end
+ end
+ RUBY
+
+ add_to_config <<-RUBY
+ sha1_secret = Rails.application.key_generator.generate_key("sha1")
+ sha256_secret = Rails.application.key_generator.generate_key("sha256")
+
+ ::TestVerifiers = Class.new do
+ class_attribute :sha1, default: ActiveSupport::MessageVerifier.new(sha1_secret, digest: "SHA1")
+ class_attribute :sha256, default: ActiveSupport::MessageVerifier.new(sha256_secret, digest: "SHA256")
+ end
+
+ config.action_dispatch.signed_cookie_digest = "SHA512"
+ config.action_dispatch.signed_cookie_salt = "sha512 salt"
+
+ config.action_dispatch.cookies_rotations.tap do |cookies|
+ cookies.rotate :signed, sha1_secret, digest: "SHA1"
+ cookies.rotate :signed, sha256_secret, digest: "SHA256"
+ end
+ RUBY
+
+ require "#{app_path}/config/environment"
+
+ verifier_sha512 = ActiveSupport::MessageVerifier.new(app.key_generator.generate_key("sha512 salt"), digest: :SHA512)
+
+ get "/foo/write_raw_cookie_sha1"
+ get "/foo/read_signed"
+ assert_equal "signed cookie".inspect, last_response.body
+
+ get "/foo/read_raw_cookie"
+ assert_equal "signed cookie", verifier_sha512.verify(last_response.body)
+
+ get "/foo/write_raw_cookie_sha256"
+ get "/foo/read_signed"
+ assert_equal "signed cookie".inspect, last_response.body
+
+ get "/foo/read_raw_cookie"
+ assert_equal "signed cookie", verifier_sha512.verify(last_response.body)
+ end
+
+ test "encrypted cookies rotating multiple encryption keys" do
+ app_file "config/routes.rb", <<-RUBY
+ Rails.application.routes.draw do
+ get ':controller(/:action)'
+ post ':controller(/:action)'
+ end
+ RUBY
+
+ controller :foo, <<-RUBY
+ class FooController < ActionController::Base
+ protect_from_forgery with: :null_session
+
+ def write_raw_cookie_one
+ cookies[:encrypted_cookie] = TestEncryptors.first_gcm.encrypt_and_sign("encrypted cookie")
+ head :ok
+ end
+
+ def write_raw_cookie_two
+ cookies[:encrypted_cookie] = TestEncryptors.second_gcm.encrypt_and_sign("encrypted cookie")
+ head :ok
+ end
+
+ def read_encrypted
+ render plain: cookies.encrypted[:encrypted_cookie].inspect
+ end
+
+ def read_raw_cookie
+ render plain: cookies[:encrypted_cookie]
+ end
+ end
+ RUBY
+
+ add_to_config <<-RUBY
+ first_secret = Rails.application.key_generator.generate_key("first", 32)
+ second_secret = Rails.application.key_generator.generate_key("second", 32)
+
+ ::TestEncryptors = Class.new do
+ class_attribute :first_gcm, default: ActiveSupport::MessageEncryptor.new(first_secret, cipher: "aes-256-gcm")
+ class_attribute :second_gcm, default: ActiveSupport::MessageEncryptor.new(second_secret, cipher: "aes-256-gcm")
+ end
+
+ config.action_dispatch.use_authenticated_cookie_encryption = true
+ config.action_dispatch.encrypted_cookie_cipher = "aes-256-gcm"
+ config.action_dispatch.authenticated_encrypted_cookie_salt = "salt"
+
+ config.action_dispatch.cookies_rotations.tap do |cookies|
+ cookies.rotate :encrypted, first_secret
+ cookies.rotate :encrypted, second_secret
+ end
+ RUBY
+
+ require "#{app_path}/config/environment"
+
+ encryptor = ActiveSupport::MessageEncryptor.new(app.key_generator.generate_key("salt", 32), cipher: "aes-256-gcm")
+
+ get "/foo/write_raw_cookie_one"
+ get "/foo/read_encrypted"
+ assert_equal "encrypted cookie".inspect, last_response.body
+
+ get "/foo/read_raw_cookie"
+ assert_equal "encrypted cookie", encryptor.decrypt_and_verify(last_response.body)
+
+ get "/foo/write_raw_cookie_sha256"
+ get "/foo/read_encrypted"
+ assert_equal "encrypted cookie".inspect, last_response.body
+
+ get "/foo/read_raw_cookie"
+ assert_equal "encrypted cookie", encryptor.decrypt_and_verify(last_response.body)
+ end
end
end
diff --git a/railties/test/application/middleware/exceptions_test.rb b/railties/test/application/middleware/exceptions_test.rb
index fe07ad3cbe..2d659ade8d 100644
--- a/railties/test/application/middleware/exceptions_test.rb
+++ b/railties/test/application/middleware/exceptions_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
require "rack/test"
@@ -100,7 +102,7 @@ module ApplicationTests
end
end
- test "routing to an nonexistent controller when action_dispatch.show_exceptions and consider_all_requests_local are set shows diagnostics" do
+ test "routing to a nonexistent controller when action_dispatch.show_exceptions and consider_all_requests_local are set shows diagnostics" do
app_file "config/routes.rb", <<-RUBY
Rails.application.routes.draw do
resources :articles
diff --git a/railties/test/application/middleware/remote_ip_test.rb b/railties/test/application/middleware/remote_ip_test.rb
index c34d9d6ee7..83cf8a27f7 100644
--- a/railties/test/application/middleware/remote_ip_test.rb
+++ b/railties/test/application/middleware/remote_ip_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "ipaddr"
require "isolation/abstract_unit"
require "active_support/key_generator"
diff --git a/railties/test/application/middleware/sendfile_test.rb b/railties/test/application/middleware/sendfile_test.rb
index 4938402fdc..9def3a0ce7 100644
--- a/railties/test/application/middleware/sendfile_test.rb
+++ b/railties/test/application/middleware/sendfile_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
module ApplicationTests
@@ -13,10 +15,6 @@ module ApplicationTests
teardown_app
end
- def app
- @app ||= Rails.application
- end
-
define_method :simple_controller do
class ::OmgController < ActionController::Base
def index
diff --git a/railties/test/application/middleware/session_test.rb b/railties/test/application/middleware/session_test.rb
index a14ea589ed..a17988235a 100644
--- a/railties/test/application/middleware/session_test.rb
+++ b/railties/test/application/middleware/session_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
require "rack/test"
@@ -335,31 +337,37 @@ module ApplicationTests
add_to_config <<-RUBY
# Use a static key
- secrets.secret_key_base = "known key base"
+ Rails.application.credentials.secret_key_base = "known key base"
# Enable AEAD cookies
config.action_dispatch.use_authenticated_cookie_encryption = true
RUBY
- require "#{app_path}/config/environment"
+ begin
+ old_rails_env, ENV["RAILS_ENV"] = ENV["RAILS_ENV"], "production"
- get "/foo/write_raw_session"
- get "/foo/read_session"
- assert_equal "1", last_response.body
+ require "#{app_path}/config/environment"
- get "/foo/write_session"
- get "/foo/read_session"
- assert_equal "2", last_response.body
+ get "/foo/write_raw_session"
+ get "/foo/read_session"
+ assert_equal "1", last_response.body
- get "/foo/read_encrypted_cookie"
- assert_equal "2", last_response.body
+ get "/foo/write_session"
+ get "/foo/read_session"
+ assert_equal "2", last_response.body
- cipher = "aes-256-gcm"
- secret = app.key_generator.generate_key("authenticated encrypted cookie")
- encryptor = ActiveSupport::MessageEncryptor.new(secret[0, ActiveSupport::MessageEncryptor.key_len(cipher)], cipher: cipher)
+ get "/foo/read_encrypted_cookie"
+ assert_equal "2", last_response.body
- get "/foo/read_raw_cookie"
- assert_equal 2, encryptor.decrypt_and_verify(last_response.body)["foo"]
+ cipher = "aes-256-gcm"
+ secret = app.key_generator.generate_key("authenticated encrypted cookie")
+ encryptor = ActiveSupport::MessageEncryptor.new(secret[0, ActiveSupport::MessageEncryptor.key_len(cipher)], cipher: cipher)
+
+ get "/foo/read_raw_cookie"
+ assert_equal 2, encryptor.decrypt_and_verify(last_response.body)["foo"]
+ ensure
+ ENV["RAILS_ENV"] = old_rails_env
+ end
end
test "session upgrading legacy signed cookies to new signed cookies" do
@@ -398,26 +406,32 @@ module ApplicationTests
add_to_config <<-RUBY
secrets.secret_token = "3b7cd727ee24e8444053437c36cc66c4"
- secrets.secret_key_base = nil
+ Rails.application.credentials.secret_key_base = nil
RUBY
- require "#{app_path}/config/environment"
+ begin
+ old_rails_env, ENV["RAILS_ENV"] = ENV["RAILS_ENV"], "production"
- get "/foo/write_raw_session"
- get "/foo/read_session"
- assert_equal "1", last_response.body
+ require "#{app_path}/config/environment"
- get "/foo/write_session"
- get "/foo/read_session"
- assert_equal "2", last_response.body
+ get "/foo/write_raw_session"
+ get "/foo/read_session"
+ assert_equal "1", last_response.body
- get "/foo/read_signed_cookie"
- assert_equal "2", last_response.body
+ get "/foo/write_session"
+ get "/foo/read_session"
+ assert_equal "2", last_response.body
- verifier = ActiveSupport::MessageVerifier.new(app.secrets.secret_token)
+ get "/foo/read_signed_cookie"
+ assert_equal "2", last_response.body
- get "/foo/read_raw_cookie"
- assert_equal 2, verifier.verify(last_response.body)["foo"]
+ verifier = ActiveSupport::MessageVerifier.new(app.secrets.secret_token)
+
+ get "/foo/read_raw_cookie"
+ assert_equal 2, verifier.verify(last_response.body)["foo"]
+ ensure
+ ENV["RAILS_ENV"] = old_rails_env
+ end
end
test "calling reset_session on request does not trigger an error for API apps" do
diff --git a/railties/test/application/middleware/static_test.rb b/railties/test/application/middleware/static_test.rb
index 5cd3e4325e..0977042cfe 100644
--- a/railties/test/application/middleware/static_test.rb
+++ b/railties/test/application/middleware/static_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
require "rack/test"
diff --git a/railties/test/application/middleware_test.rb b/railties/test/application/middleware_test.rb
index 0a6e5b52e9..0a5a524692 100644
--- a/railties/test/application/middleware_test.rb
+++ b/railties/test/application/middleware_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
module ApplicationTests
@@ -274,7 +276,7 @@ module ApplicationTests
assert_equal "max-age=0, private, must-revalidate", last_response.headers["Cache-Control"]
assert_equal etag, last_response.headers["Etag"]
- get "/", {}, "HTTP_IF_NONE_MATCH" => etag
+ get "/", {}, { "HTTP_IF_NONE_MATCH" => etag }
assert_equal 304, last_response.status
assert_equal "", last_response.body
assert_nil last_response.headers["Content-Type"]
diff --git a/railties/test/application/multiple_applications_test.rb b/railties/test/application/multiple_applications_test.rb
index 26b810af73..d6c81c1fe2 100644
--- a/railties/test/application/multiple_applications_test.rb
+++ b/railties/test/application/multiple_applications_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
module ApplicationTests
diff --git a/railties/test/application/paths_test.rb b/railties/test/application/paths_test.rb
index 515205296c..0abc5cc9aa 100644
--- a/railties/test/application/paths_test.rb
+++ b/railties/test/application/paths_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
module ApplicationTests
diff --git a/railties/test/application/per_request_digest_cache_test.rb b/railties/test/application/per_request_digest_cache_test.rb
index 6e6996a6ba..e9bc91785c 100644
--- a/railties/test/application/per_request_digest_cache_test.rb
+++ b/railties/test/application/per_request_digest_cache_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
require "rack/test"
require "minitest/mock"
diff --git a/railties/test/application/rack/logger_test.rb b/railties/test/application/rack/logger_test.rb
index e71bcbc536..d949a48366 100644
--- a/railties/test/application/rack/logger_test.rb
+++ b/railties/test/application/rack/logger_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
require "active_support/log_subscriber/test_helper"
require "rack/test"
diff --git a/railties/test/application/rackup_test.rb b/railties/test/application/rackup_test.rb
index 2943e9ee5d..383f18a7da 100644
--- a/railties/test/application/rackup_test.rb
+++ b/railties/test/application/rackup_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
module ApplicationTests
diff --git a/railties/test/application/rake/dbs_test.rb b/railties/test/application/rake/dbs_test.rb
index c63f23fa0a..0235210fdd 100644
--- a/railties/test/application/rake/dbs_test.rb
+++ b/railties/test/application/rake/dbs_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
module ApplicationTests
@@ -24,13 +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 = `bin/rails db:create`
+ output = rails("db:create")
assert_match(/Created database/, output)
assert File.exist?(expected_database)
- assert_equal expected_database, ActiveRecord::Base.connection_config[:database]
- output = `bin/rails db:drop`
+ assert_equal expected_database, ActiveRecord::Base.connection_config[:database] if environment_loaded
+ output = rails("db:drop")
assert_match(/Dropped database/, output)
assert !File.exist?(expected_database)
end
@@ -47,20 +49,35 @@ module ApplicationTests
db_create_and_drop database_url_db_name
end
+ test "db:create and db:drop respect environment setting" do
+ app_file "config/database.yml", <<-YAML
+ development:
+ database: <%= Rails.application.config.database %>
+ adapter: sqlite3
+ YAML
+
+ app_file "config/environments/development.rb", <<-RUBY
+ Rails.application.configure do
+ config.database = "db/development.sqlite3"
+ end
+ RUBY
+
+ db_create_and_drop "db/development.sqlite3", environment_loaded: false
+ end
+
def with_database_existing
Dir.chdir(app_path) do
set_database_url
- `bin/rails db:create`
+ rails "db:create"
yield
- `bin/rails db:drop`
+ rails "db:drop"
end
end
test "db:create failure because database exists" do
with_database_existing do
- output = `bin/rails db:create 2>&1`
+ output = rails("db:create")
assert_match(/already exists/, output)
- assert_equal 0, $?.exitstatus
end
end
@@ -75,24 +92,21 @@ module ApplicationTests
test "db:create failure because bad permissions" do
with_bad_permissions do
- output = `bin/rails db:create 2>&1`
+ output = rails("db:create", allow_failure: true)
assert_match(/Couldn't create database/, output)
assert_equal 1, $?.exitstatus
end
end
test "db:drop failure because database does not exist" do
- Dir.chdir(app_path) do
- output = `bin/rails db:drop:_unsafe --trace 2>&1`
- assert_match(/does not exist/, output)
- assert_equal 0, $?.exitstatus
- end
+ output = rails("db:drop:_unsafe", "--trace")
+ assert_match(/does not exist/, output)
end
test "db:drop failure because bad permissions" do
with_database_existing do
with_bad_permissions do
- output = `bin/rails db:drop 2>&1`
+ output = rails("db:drop", allow_failure: true)
assert_match(/Couldn't drop/, output)
assert_equal 1, $?.exitstatus
end
@@ -100,13 +114,11 @@ module ApplicationTests
end
def db_migrate_and_status(expected_database)
- Dir.chdir(app_path) do
- `bin/rails generate model book title:string;
- bin/rails db:migrate`
- output = `bin/rails db:migrate:status`
- assert_match(%r{database:\s+\S*#{Regexp.escape(expected_database)}}, output)
- assert_match(/up\s+\d{14}\s+Create books/, output)
- end
+ rails "generate", "model", "book", "title:string"
+ rails "db:migrate"
+ output = rails("db:migrate:status")
+ assert_match(%r{database:\s+\S*#{Regexp.escape(expected_database)}}, output)
+ assert_match(/up\s+\d{14}\s+Create books/, output)
end
test "db:migrate and db:migrate:status without database_url" do
@@ -122,8 +134,8 @@ module ApplicationTests
def db_schema_dump
Dir.chdir(app_path) do
- `bin/rails generate model book title:string;
- bin/rails db:migrate db:schema:dump`
+ rails "generate", "model", "book", "title:string"
+ rails "db:migrate", "db:schema:dump"
schema_dump = File.read("db/schema.rb")
assert_match(/create_table \"books\"/, schema_dump)
end
@@ -140,8 +152,8 @@ module ApplicationTests
def db_fixtures_load(expected_database)
Dir.chdir(app_path) do
- `bin/rails generate model book title:string;
- bin/rails db:migrate db:fixtures:load`
+ rails "generate", "model", "book", "title:string"
+ rails "db:migrate", "db:fixtures:load"
assert_match expected_database, ActiveRecord::Base.connection_config[:database]
require "#{app_path}/app/models/book"
assert_equal 2, Book.count
@@ -161,21 +173,20 @@ module ApplicationTests
test "db:fixtures:load with namespaced fixture" do
require "#{app_path}/config/environment"
- Dir.chdir(app_path) do
- `bin/rails generate model admin::book title:string;
- bin/rails db:migrate db:fixtures:load`
- require "#{app_path}/app/models/admin/book"
- assert_equal 2, Admin::Book.count
- end
+
+ rails "generate", "model", "admin::book", "title:string"
+ rails "db:migrate", "db:fixtures:load"
+ require "#{app_path}/app/models/admin/book"
+ assert_equal 2, Admin::Book.count
end
def db_structure_dump_and_load(expected_database)
Dir.chdir(app_path) do
- `bin/rails generate model book title:string;
- bin/rails db:migrate db:structure:dump`
+ rails "generate", "model", "book", "title:string"
+ rails "db:migrate", "db:structure:dump"
structure_dump = File.read("db/structure.sql")
assert_match(/CREATE TABLE (?:IF NOT EXISTS )?\"books\"/, structure_dump)
- `bin/rails environment db:drop db:structure:load`
+ rails "environment", "db:drop", "db:structure:load"
assert_match expected_database, ActiveRecord::Base.connection_config[:database]
require "#{app_path}/app/models/book"
#if structure is not loaded correctly, exception would be raised
@@ -194,75 +205,82 @@ module ApplicationTests
db_structure_dump_and_load database_url_db_name
end
+ test "db:structure:dump and db:structure:load set ar_internal_metadata" do
+ require "#{app_path}/config/environment"
+ db_structure_dump_and_load ActiveRecord::Base.configurations[Rails.env]["database"]
+
+ assert_equal "test", rails("runner", "-e", "test", "puts ActiveRecord::InternalMetadata[:environment]").strip
+ assert_equal "development", rails("runner", "puts ActiveRecord::InternalMetadata[:environment]").strip
+ end
+
test "db:structure:dump does not dump schema information when no migrations are used" do
- Dir.chdir(app_path) do
- # create table without migrations
- `bin/rails runner 'ActiveRecord::Base.connection.create_table(:posts) {|t| t.string :title }'`
+ # create table without migrations
+ rails "runner", "ActiveRecord::Base.connection.create_table(:posts) {|t| t.string :title }"
- stderr_output = capture(:stderr) { `bin/rails db:structure:dump` }
- assert_empty stderr_output
- structure_dump = File.read("db/structure.sql")
- assert_match(/CREATE TABLE (?:IF NOT EXISTS )?\"posts\"/, structure_dump)
- end
+ stderr_output = capture(:stderr) { rails("db:structure:dump", stderr: true, allow_failure: true) }
+ assert_empty stderr_output
+ structure_dump = File.read("#{app_path}/db/structure.sql")
+ assert_match(/CREATE TABLE (?:IF NOT EXISTS )?\"posts\"/, structure_dump)
end
test "db:schema:load and db:structure:load do not purge the existing database" do
- Dir.chdir(app_path) do
- `bin/rails runner 'ActiveRecord::Base.connection.create_table(:posts) {|t| t.string :title }'`
+ rails "runner", "ActiveRecord::Base.connection.create_table(:posts) {|t| t.string :title }"
- app_file "db/schema.rb", <<-RUBY
- ActiveRecord::Schema.define(version: 20140423102712) do
- create_table(:comments) {}
- end
- RUBY
+ app_file "db/schema.rb", <<-RUBY
+ ActiveRecord::Schema.define(version: 20140423102712) do
+ create_table(:comments) {}
+ end
+ RUBY
- list_tables = lambda { `bin/rails runner 'p ActiveRecord::Base.connection.tables'`.strip }
+ list_tables = lambda { rails("runner", "p ActiveRecord::Base.connection.tables").strip }
- assert_equal '["posts"]', list_tables[]
- `bin/rails db:schema:load`
- assert_equal '["posts", "comments", "schema_migrations", "ar_internal_metadata"]', list_tables[]
+ assert_equal '["posts"]', list_tables[]
+ rails "db:schema:load"
+ assert_equal '["posts", "comments", "schema_migrations", "ar_internal_metadata"]', list_tables[]
- app_file "db/structure.sql", <<-SQL
- CREATE TABLE "users" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar(255));
- SQL
+ app_file "db/structure.sql", <<-SQL
+ CREATE TABLE "users" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar(255));
+ SQL
- `bin/rails db:structure:load`
- assert_equal '["posts", "comments", "schema_migrations", "ar_internal_metadata", "users"]', list_tables[]
- end
+ rails "db:structure:load"
+ assert_equal '["posts", "comments", "schema_migrations", "ar_internal_metadata", "users"]', list_tables[]
end
test "db:schema:load with inflections" do
- Dir.chdir(app_path) do
- app_file "config/initializers/inflection.rb", <<-RUBY
- ActiveSupport::Inflector.inflections do |inflect|
- inflect.irregular 'goose', 'geese'
- end
- RUBY
- app_file "config/initializers/primary_key_table_name.rb", <<-RUBY
- ActiveRecord::Base.primary_key_prefix_type = :table_name
- RUBY
- app_file "db/schema.rb", <<-RUBY
- ActiveRecord::Schema.define(version: 20140423102712) do
- create_table("goose".pluralize) do |t|
- t.string :name
- end
+ app_file "config/initializers/inflection.rb", <<-RUBY
+ ActiveSupport::Inflector.inflections do |inflect|
+ inflect.irregular 'goose', 'geese'
+ end
+ RUBY
+ app_file "config/initializers/primary_key_table_name.rb", <<-RUBY
+ ActiveRecord::Base.primary_key_prefix_type = :table_name
+ RUBY
+ app_file "db/schema.rb", <<-RUBY
+ ActiveRecord::Schema.define(version: 20140423102712) do
+ create_table("goose".pluralize) do |t|
+ t.string :name
end
- RUBY
+ end
+ RUBY
- `bin/rails db:schema:load`
+ rails "db:schema:load"
- tables = `bin/rails runner 'p ActiveRecord::Base.connection.tables'`.strip
- assert_match(/"geese"/, tables)
+ tables = rails("runner", "p ActiveRecord::Base.connection.tables").strip
+ assert_match(/"geese"/, tables)
- columns = `bin/rails runner 'p ActiveRecord::Base.connection.columns("geese").map(&:name)'`.strip
- assert_equal columns, '["gooseid", "name"]'
- end
+ columns = rails("runner", "p ActiveRecord::Base.connection.columns('geese').map(&:name)").strip
+ assert_equal columns, '["gooseid", "name"]'
+ end
+
+ test "db:schema:load fails if schema.rb doesn't exist yet" do
+ stderr_output = capture(:stderr) { rails("db:schema:load", stderr: true, allow_failure: true) }
+ assert_match(/Run `rails db:migrate` to create it/, stderr_output)
end
def db_test_load_structure
Dir.chdir(app_path) do
- `bin/rails generate model book title:string;
- bin/rails db:migrate db:structure:dump db:test:load_structure`
+ rails "generate", "model", "book", "title:string"
+ rails "db:migrate", "db:structure:dump", "db:test:load_structure"
ActiveRecord::Base.configurations = Rails.application.config.database_configuration
ActiveRecord::Base.establish_connection :test
require "#{app_path}/app/models/book"
@@ -297,15 +315,52 @@ module ApplicationTests
puts ActiveRecord::Base.connection_config[:database]
RUBY
- Dir.chdir(app_path) do
- database_path = `bin/rails db:setup`
- assert_equal "development.sqlite3", File.basename(database_path.strip)
- end
+ database_path = rails("db:setup")
+ assert_equal "development.sqlite3", File.basename(database_path.strip)
ensure
ENV["RAILS_ENV"] = @old_rails_env
ENV["RACK_ENV"] = @old_rack_env
end
end
+
+ test "db:setup sets ar_internal_metadata" do
+ app_file "db/schema.rb", ""
+ rails "db:setup"
+
+ test_environment = lambda { rails("runner", "-e", "test", "puts ActiveRecord::InternalMetadata[:environment]").strip }
+ development_environment = lambda { rails("runner", "puts ActiveRecord::InternalMetadata[:environment]").strip }
+
+ assert_equal "test", test_environment.call
+ assert_equal "development", development_environment.call
+
+ app_file "db/structure.sql", ""
+ app_file "config/initializers/enable_sql_schema_format.rb", <<-RUBY
+ Rails.application.config.active_record.schema_format = :sql
+ RUBY
+
+ rails "db:setup"
+
+ assert_equal "test", test_environment.call
+ assert_equal "development", development_environment.call
+ end
+
+ test "db:test:prepare sets test ar_internal_metadata" do
+ app_file "db/schema.rb", ""
+ rails "db:test:prepare"
+
+ test_environment = lambda { rails("runner", "-e", "test", "puts ActiveRecord::InternalMetadata[:environment]").strip }
+
+ assert_equal "test", test_environment.call
+
+ app_file "db/structure.sql", ""
+ app_file "config/initializers/enable_sql_schema_format.rb", <<-RUBY
+ Rails.application.config.active_record.schema_format = :sql
+ RUBY
+
+ rails "db:test:prepare"
+
+ assert_equal "test", test_environment.call
+ end
end
end
end
diff --git a/railties/test/application/rake/dev_test.rb b/railties/test/application/rake/dev_test.rb
index 4f992d9c8d..66e1ac9d99 100644
--- a/railties/test/application/rake/dev_test.rb
+++ b/railties/test/application/rake/dev_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
module ApplicationTests
@@ -15,7 +17,7 @@ module ApplicationTests
test "dev:cache creates file and outputs message" do
Dir.chdir(app_path) do
- output = `rails dev:cache`
+ output = rails("dev:cache")
assert File.exist?("tmp/caching-dev.txt")
assert_match(/Development mode is now being cached/, output)
end
@@ -23,19 +25,23 @@ module ApplicationTests
test "dev:cache deletes file and outputs message" do
Dir.chdir(app_path) do
- `rails dev:cache` # Create caching file.
- output = `rails dev:cache` # Delete caching file.
+ rails "dev:cache" # Create caching file.
+ output = rails("dev:cache") # Delete caching file.
assert_not File.exist?("tmp/caching-dev.txt")
assert_match(/Development mode is no longer being cached/, output)
end
end
- test "dev:cache removes server.pid also" do
+ test "dev:cache touches tmp/restart.txt" do
Dir.chdir(app_path) do
- FileUtils.mkdir_p("tmp/pids")
- FileUtils.touch("tmp/pids/server.pid")
- `rails dev:cache`
- assert_not File.exist?("tmp/pids/server.pid")
+ rails "dev:cache"
+ assert File.exist?("tmp/restart.txt")
+
+ prev_mtime = File.mtime("tmp/restart.txt")
+ sleep(1)
+ rails "dev:cache"
+ curr_mtime = File.mtime("tmp/restart.txt")
+ assert_not_equal prev_mtime, curr_mtime
end
end
end
diff --git a/railties/test/application/rake/framework_test.rb b/railties/test/application/rake/framework_test.rb
index 40488a6aab..644b1924b5 100644
--- a/railties/test/application/rake/framework_test.rb
+++ b/railties/test/application/rake/framework_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
module ApplicationTests
diff --git a/railties/test/application/rake/log_test.rb b/railties/test/application/rake/log_test.rb
index fdd3c71fe8..678f26db26 100644
--- a/railties/test/application/rake/log_test.rb
+++ b/railties/test/application/rake/log_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
module ApplicationTests
@@ -21,7 +23,7 @@ module ApplicationTests
File.write("log/test.log", "test")
File.write("log/dummy.log", "dummy")
- `rails log:clear`
+ rails "log:clear"
assert_equal 0, File.size("log/test.log")
assert_equal 0, File.size("log/staging.log")
diff --git a/railties/test/application/rake/migrations_test.rb b/railties/test/application/rake/migrations_test.rb
index 51dfe2ef98..788f9160d6 100644
--- a/railties/test/application/rake/migrations_test.rb
+++ b/railties/test/application/rake/migrations_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
module ApplicationTests
@@ -13,263 +15,396 @@ module ApplicationTests
end
test "running migrations with given scope" do
- Dir.chdir(app_path) do
- `bin/rails generate model user username:string password:string`
+ rails "generate", "model", "user", "username:string", "password:string"
- app_file "db/migrate/01_a_migration.bukkits.rb", <<-MIGRATION
- class AMigration < ActiveRecord::Migration::Current
- end
- MIGRATION
+ app_file "db/migrate/01_a_migration.bukkits.rb", <<-MIGRATION
+ class AMigration < ActiveRecord::Migration::Current
+ end
+ MIGRATION
- output = `bin/rails db:migrate SCOPE=bukkits`
- assert_no_match(/create_table\(:users\)/, output)
- assert_no_match(/CreateUsers/, output)
- assert_no_match(/add_column\(:users, :email, :string\)/, output)
+ output = rails("db:migrate", "SCOPE=bukkits")
+ assert_no_match(/create_table\(:users\)/, output)
+ assert_no_match(/CreateUsers/, output)
+ assert_no_match(/add_column\(:users, :email, :string\)/, output)
- assert_match(/AMigration: migrated/, output)
+ assert_match(/AMigration: migrated/, output)
- output = `bin/rails db:migrate SCOPE=bukkits VERSION=0`
- assert_no_match(/drop_table\(:users\)/, output)
- assert_no_match(/CreateUsers/, output)
- assert_no_match(/remove_column\(:users, :email\)/, output)
+ output = rails("db:migrate", "SCOPE=bukkits", "VERSION=0")
+ assert_no_match(/drop_table\(:users\)/, output)
+ assert_no_match(/CreateUsers/, output)
+ assert_no_match(/remove_column\(:users, :email\)/, output)
- assert_match(/AMigration: reverted/, output)
- end
+ assert_match(/AMigration: reverted/, output)
+ end
+
+ test "migrate with specified VERSION in different formats" do
+ app_file "db/migrate/01_one_migration.rb", <<-MIGRATION
+ class OneMigration < ActiveRecord::Migration::Current
+ end
+ MIGRATION
+
+ app_file "db/migrate/02_two_migration.rb", <<-MIGRATION
+ class TwoMigration < ActiveRecord::Migration::Current
+ end
+ MIGRATION
+
+ app_file "db/migrate/03_three_migration.rb", <<-MIGRATION
+ class ThreeMigration < ActiveRecord::Migration::Current
+ end
+ MIGRATION
+
+ rails "db:migrate"
+
+ output = rails("db:migrate:status")
+ assert_match(/up\s+001\s+One migration/, output)
+ assert_match(/up\s+002\s+Two migration/, output)
+ assert_match(/up\s+003\s+Three migration/, output)
+
+ rails "db:migrate", "VERSION=01_one_migration.rb"
+ output = rails("db:migrate:status")
+ assert_match(/up\s+001\s+One migration/, output)
+ assert_match(/down\s+002\s+Two migration/, output)
+ assert_match(/down\s+003\s+Three migration/, output)
+
+ rails "db:migrate", "VERSION=3"
+ output = rails("db:migrate:status")
+ assert_match(/up\s+001\s+One migration/, output)
+ assert_match(/up\s+002\s+Two migration/, output)
+ assert_match(/up\s+003\s+Three migration/, output)
+
+ rails "db:migrate", "VERSION=001"
+ output = rails("db:migrate:status")
+ assert_match(/up\s+001\s+One migration/, output)
+ assert_match(/down\s+002\s+Two migration/, output)
+ assert_match(/down\s+003\s+Three migration/, output)
end
test "migration with empty version" do
- Dir.chdir(app_path) do
- output = `bin/rails db:migrate VERSION= 2>&1`
- assert_match(/Empty VERSION provided/, output)
+ app_file "db/migrate/01_one_migration.rb", <<-MIGRATION
+ class OneMigration < ActiveRecord::Migration::Current
+ end
+ MIGRATION
- output = `bin/rails db:migrate:redo VERSION= 2>&1`
- assert_match(/Empty VERSION provided/, output)
+ app_file "db/migrate/02_two_migration.rb", <<-MIGRATION
+ class TwoMigration < ActiveRecord::Migration::Current
+ end
+ MIGRATION
- output = `bin/rails db:migrate:up VERSION= 2>&1`
- assert_match(/VERSION is required/, output)
+ rails("db:migrate", "VERSION=")
- output = `bin/rails db:migrate:up 2>&1`
- assert_match(/VERSION is required/, output)
+ output = rails("db:migrate:status")
+ assert_match(/up\s+001\s+One migration/, output)
+ assert_match(/up\s+002\s+Two migration/, output)
- output = `bin/rails db:migrate:down VERSION= 2>&1`
- assert_match(/VERSION is required - To go down one migration, use db:rollback/, output)
+ output = rails("db:migrate:redo", "VERSION=", allow_failure: true)
+ assert_match(/Empty VERSION provided/, output)
- output = `bin/rails db:migrate:down 2>&1`
- assert_match(/VERSION is required - To go down one migration, use db:rollback/, output)
- end
+ output = rails("db:migrate:up", "VERSION=", allow_failure: true)
+ assert_match(/VERSION is required/, output)
+
+ output = rails("db:migrate:up", allow_failure: true)
+ assert_match(/VERSION is required/, output)
+
+ output = rails("db:migrate:down", "VERSION=", allow_failure: true)
+ assert_match(/VERSION is required - To go down one migration, use db:rollback/, output)
+
+ output = rails("db:migrate:down", allow_failure: true)
+ assert_match(/VERSION is required - To go down one migration, use db:rollback/, output)
+
+ output = rails("db:migrate:status")
+ assert_match(/up\s+001\s+One migration/, output)
+ assert_match(/up\s+002\s+Two migration/, output)
+ end
+
+ test "migration with 0 version" do
+ app_file "db/migrate/01_one_migration.rb", <<-MIGRATION
+ class OneMigration < ActiveRecord::Migration::Current
+ end
+ MIGRATION
+
+ app_file "db/migrate/02_two_migration.rb", <<-MIGRATION
+ class TwoMigration < ActiveRecord::Migration::Current
+ end
+ MIGRATION
+
+ rails "db:migrate"
+
+ output = rails("db:migrate:status")
+ assert_match(/up\s+001\s+One migration/, output)
+ assert_match(/up\s+002\s+Two migration/, output)
+
+ rails "db:migrate", "VERSION=0"
+
+ output = rails("db:migrate:status")
+ assert_match(/down\s+001\s+One migration/, output)
+ assert_match(/down\s+002\s+Two migration/, output)
end
test "model and migration generator with change syntax" do
- Dir.chdir(app_path) do
- `bin/rails generate model user username:string password:string;
- bin/rails generate migration add_email_to_users email:string`
-
- output = `bin/rails db:migrate`
- assert_match(/create_table\(:users\)/, output)
- assert_match(/CreateUsers: migrated/, output)
- assert_match(/add_column\(:users, :email, :string\)/, output)
- assert_match(/AddEmailToUsers: migrated/, output)
-
- output = `bin/rails db:rollback STEP=2`
- assert_match(/drop_table\(:users\)/, output)
- assert_match(/CreateUsers: reverted/, output)
- assert_match(/remove_column\(:users, :email, :string\)/, output)
- assert_match(/AddEmailToUsers: reverted/, output)
- end
+ rails "generate", "model", "user", "username:string", "password:string"
+ rails "generate", "migration", "add_email_to_users", "email:string"
+
+ output = rails("db:migrate")
+ assert_match(/create_table\(:users\)/, output)
+ assert_match(/CreateUsers: migrated/, output)
+ assert_match(/add_column\(:users, :email, :string\)/, output)
+ assert_match(/AddEmailToUsers: migrated/, output)
+
+ output = rails("db:rollback", "STEP=2")
+ assert_match(/drop_table\(:users\)/, output)
+ assert_match(/CreateUsers: reverted/, output)
+ assert_match(/remove_column\(:users, :email, :string\)/, output)
+ assert_match(/AddEmailToUsers: reverted/, output)
end
test "migration status when schema migrations table is not present" do
- output = Dir.chdir(app_path) { `bin/rails db:migrate:status 2>&1` }
+ output = rails("db:migrate:status", allow_failure: true)
assert_equal "Schema migrations table does not exist yet.\n", output
end
test "migration status" do
- Dir.chdir(app_path) do
- `bin/rails generate model user username:string password:string;
- bin/rails generate migration add_email_to_users email:string;
- bin/rails db:migrate`
+ rails "generate", "model", "user", "username:string", "password:string"
+ rails "generate", "migration", "add_email_to_users", "email:string"
+ rails "db:migrate"
- output = `bin/rails db:migrate:status`
+ output = rails("db:migrate:status")
- assert_match(/up\s+\d{14}\s+Create users/, output)
- assert_match(/up\s+\d{14}\s+Add email to users/, output)
+ assert_match(/up\s+\d{14}\s+Create users/, output)
+ assert_match(/up\s+\d{14}\s+Add email to users/, output)
- `bin/rails db:rollback STEP=1`
- output = `bin/rails db:migrate:status`
+ rails "db:rollback", "STEP=1"
+ output = rails("db:migrate:status")
- assert_match(/up\s+\d{14}\s+Create users/, output)
- assert_match(/down\s+\d{14}\s+Add email to users/, output)
- end
+ assert_match(/up\s+\d{14}\s+Create users/, output)
+ assert_match(/down\s+\d{14}\s+Add email to users/, output)
end
test "migration status without timestamps" do
add_to_config("config.active_record.timestamped_migrations = false")
- Dir.chdir(app_path) do
- `bin/rails generate model user username:string password:string;
- bin/rails generate migration add_email_to_users email:string;
- bin/rails db:migrate`
+ rails "generate", "model", "user", "username:string", "password:string"
+ rails "generate", "migration", "add_email_to_users", "email:string"
+ rails "db:migrate"
- output = `bin/rails db:migrate:status`
+ output = rails("db:migrate:status")
- assert_match(/up\s+\d{3,}\s+Create users/, output)
- assert_match(/up\s+\d{3,}\s+Add email to users/, output)
+ assert_match(/up\s+\d{3,}\s+Create users/, output)
+ assert_match(/up\s+\d{3,}\s+Add email to users/, output)
- `bin/rails db:rollback STEP=1`
- output = `bin/rails db:migrate:status`
+ rails "db:rollback", "STEP=1"
+ output = rails("db:migrate:status")
- assert_match(/up\s+\d{3,}\s+Create users/, output)
- assert_match(/down\s+\d{3,}\s+Add email to users/, output)
- end
+ assert_match(/up\s+\d{3,}\s+Create users/, output)
+ assert_match(/down\s+\d{3,}\s+Add email to users/, output)
end
test "migration status after rollback and redo" do
- Dir.chdir(app_path) do
- `bin/rails generate model user username:string password:string;
- bin/rails generate migration add_email_to_users email:string;
- bin/rails db:migrate`
+ rails "generate", "model", "user", "username:string", "password:string"
+ rails "generate", "migration", "add_email_to_users", "email:string"
+ rails "db:migrate"
- output = `bin/rails db:migrate:status`
+ output = rails("db:migrate:status")
- assert_match(/up\s+\d{14}\s+Create users/, output)
- assert_match(/up\s+\d{14}\s+Add email to users/, output)
+ assert_match(/up\s+\d{14}\s+Create users/, output)
+ assert_match(/up\s+\d{14}\s+Add email to users/, output)
- `bin/rails db:rollback STEP=2`
- output = `bin/rails db:migrate:status`
+ rails "db:rollback", "STEP=2"
+ output = rails("db:migrate:status")
- assert_match(/down\s+\d{14}\s+Create users/, output)
- assert_match(/down\s+\d{14}\s+Add email to users/, output)
+ assert_match(/down\s+\d{14}\s+Create users/, output)
+ assert_match(/down\s+\d{14}\s+Add email to users/, output)
- `bin/rails db:migrate:redo`
- output = `bin/rails db:migrate:status`
+ rails "db:migrate:redo"
+ output = rails("db:migrate:status")
- assert_match(/up\s+\d{14}\s+Create users/, output)
- assert_match(/up\s+\d{14}\s+Add email to users/, output)
- end
+ assert_match(/up\s+\d{14}\s+Create users/, output)
+ assert_match(/up\s+\d{14}\s+Add email to users/, output)
end
test "migration status after rollback and forward" do
- Dir.chdir(app_path) do
- `bin/rails generate model user username:string password:string;
- bin/rails generate migration add_email_to_users email:string;
- bin/rails db:migrate`
+ rails "generate", "model", "user", "username:string", "password:string"
+ rails "generate", "migration", "add_email_to_users", "email:string"
+ rails "db:migrate"
- output = `bin/rails db:migrate:status`
+ output = rails("db:migrate:status")
- assert_match(/up\s+\d{14}\s+Create users/, output)
- assert_match(/up\s+\d{14}\s+Add email to users/, output)
+ assert_match(/up\s+\d{14}\s+Create users/, output)
+ assert_match(/up\s+\d{14}\s+Add email to users/, output)
- `bin/rails db:rollback STEP=2`
- output = `bin/rails db:migrate:status`
+ rails "db:rollback", "STEP=2"
+ output = rails("db:migrate:status")
- assert_match(/down\s+\d{14}\s+Create users/, output)
- assert_match(/down\s+\d{14}\s+Add email to users/, output)
+ assert_match(/down\s+\d{14}\s+Create users/, output)
+ assert_match(/down\s+\d{14}\s+Add email to users/, output)
- `bin/rails db:forward STEP=2`
- output = `bin/rails db:migrate:status`
+ rails "db:forward", "STEP=2"
+ output = rails("db:migrate:status")
- assert_match(/up\s+\d{14}\s+Create users/, output)
- assert_match(/up\s+\d{14}\s+Add email to users/, output)
- end
+ assert_match(/up\s+\d{14}\s+Create users/, output)
+ assert_match(/up\s+\d{14}\s+Add email to users/, output)
end
test "raise error on any move when current migration does not exist" do
Dir.chdir(app_path) do
- `bin/rails generate model user username:string password:string;
- bin/rails generate migration add_email_to_users email:string;
- bin/rails db:migrate
- rm db/migrate/*email*.rb`
+ rails "generate", "model", "user", "username:string", "password:string"
+ rails "generate", "migration", "add_email_to_users", "email:string"
+ rails "db:migrate"
+ `rm db/migrate/*email*.rb`
- output = `bin/rails db:migrate:status`
+ output = rails("db:migrate:status")
assert_match(/up\s+\d{14}\s+Create users/, output)
assert_match(/up\s+\d{14}\s+\** NO FILE \**/, output)
- output = `bin/rails db:rollback 2>&1`
+ output = rails("db:rollback", allow_failure: true)
assert_match(/rails aborted!/, output)
assert_match(/ActiveRecord::UnknownMigrationVersionError:/, output)
assert_match(/No migration with version number\s\d{14}\./, output)
- output = `bin/rails db:migrate:status`
+ output = rails("db:migrate:status")
assert_match(/up\s+\d{14}\s+Create users/, output)
assert_match(/up\s+\d{14}\s+\** NO FILE \**/, output)
- output = `bin/rails db:forward 2>&1`
+ output = rails("db:forward", allow_failure: true)
assert_match(/rails aborted!/, output)
assert_match(/ActiveRecord::UnknownMigrationVersionError:/, output)
assert_match(/No migration with version number\s\d{14}\./, output)
- output = `bin/rails db:migrate:status`
+ output = rails("db:migrate:status")
assert_match(/up\s+\d{14}\s+Create users/, output)
assert_match(/up\s+\d{14}\s+\** NO FILE \**/, output)
end
end
+ test "raise error on any move when target migration does not exist" do
+ app_file "db/migrate/01_one_migration.rb", <<-MIGRATION
+ class OneMigration < ActiveRecord::Migration::Current
+ end
+ MIGRATION
+
+ app_file "db/migrate/02_two_migration.rb", <<-MIGRATION
+ class TwoMigration < ActiveRecord::Migration::Current
+ end
+ MIGRATION
+
+ rails "db:migrate"
+
+ output = rails("db:migrate:status")
+ assert_match(/up\s+001\s+One migration/, output)
+ assert_match(/up\s+002\s+Two migration/, output)
+
+ output = rails("db:migrate", "VERSION=3", allow_failure: true)
+ assert_match(/rails aborted!/, output)
+ assert_match(/ActiveRecord::UnknownMigrationVersionError:/, output)
+ assert_match(/No migration with version number 3/, output)
+
+ output = rails("db:migrate:status")
+ assert_match(/up\s+001\s+One migration/, output)
+ assert_match(/up\s+002\s+Two migration/, output)
+ end
+
+ test "raise error on any move when VERSION has invalid format" do
+ output = rails("db:migrate", "VERSION=unknown", allow_failure: true)
+ assert_match(/rails aborted!/, output)
+ assert_match(/Invalid format of target version/, output)
+
+ output = rails("db:migrate", "VERSION=0.1.11", allow_failure: true)
+ assert_match(/rails aborted!/, output)
+ assert_match(/Invalid format of target version/, output)
+
+ output = rails("db:migrate", "VERSION=1.1.11", allow_failure: true)
+ assert_match(/rails aborted!/, output)
+ assert_match(/Invalid format of target version/, output)
+
+ output = rails("db:migrate", "VERSION='0 '", allow_failure: true)
+ assert_match(/rails aborted!/, output)
+ assert_match(/Invalid format of target version/, output)
+
+ output = rails("db:migrate", "VERSION=1.", allow_failure: true)
+ assert_match(/rails aborted!/, output)
+ assert_match(/Invalid format of target version/, output)
+
+ output = rails("db:migrate", "VERSION=1_", allow_failure: true)
+ assert_match(/rails aborted!/, output)
+ assert_match(/Invalid format of target version/, output)
+
+ output = rails("db:migrate", "VERSION=1_name", allow_failure: true)
+ assert_match(/rails aborted!/, output)
+ assert_match(/Invalid format of target version/, output)
+
+ output = rails("db:migrate:redo", "VERSION=unknown", allow_failure: true)
+ assert_match(/rails aborted!/, output)
+ assert_match(/Invalid format of target version/, output)
+
+ output = rails("db:migrate:up", "VERSION=unknown", allow_failure: true)
+ assert_match(/rails aborted!/, output)
+ assert_match(/Invalid format of target version/, output)
+
+ output = rails("db:migrate:down", "VERSION=unknown", allow_failure: true)
+ assert_match(/rails aborted!/, output)
+ assert_match(/Invalid format of target version/, output)
+ end
+
test "migration status after rollback and redo without timestamps" do
add_to_config("config.active_record.timestamped_migrations = false")
- Dir.chdir(app_path) do
- `bin/rails generate model user username:string password:string;
- bin/rails generate migration add_email_to_users email:string;
- bin/rails db:migrate`
+ rails "generate", "model", "user", "username:string", "password:string"
+ rails "generate", "migration", "add_email_to_users", "email:string"
+ rails "db:migrate"
- output = `bin/rails db:migrate:status`
+ output = rails("db:migrate:status")
- assert_match(/up\s+\d{3,}\s+Create users/, output)
- assert_match(/up\s+\d{3,}\s+Add email to users/, output)
+ assert_match(/up\s+\d{3,}\s+Create users/, output)
+ assert_match(/up\s+\d{3,}\s+Add email to users/, output)
- `bin/rails db:rollback STEP=2`
- output = `bin/rails db:migrate:status`
+ rails "db:rollback", "STEP=2"
+ output = rails("db:migrate:status")
- assert_match(/down\s+\d{3,}\s+Create users/, output)
- assert_match(/down\s+\d{3,}\s+Add email to users/, output)
+ assert_match(/down\s+\d{3,}\s+Create users/, output)
+ assert_match(/down\s+\d{3,}\s+Add email to users/, output)
- `bin/rails db:migrate:redo`
- output = `bin/rails db:migrate:status`
+ rails "db:migrate:redo"
+ output = rails("db:migrate:status")
- assert_match(/up\s+\d{3,}\s+Create users/, output)
- assert_match(/up\s+\d{3,}\s+Add email to users/, output)
- end
+ assert_match(/up\s+\d{3,}\s+Create users/, output)
+ assert_match(/up\s+\d{3,}\s+Add email to users/, output)
end
test "running migrations with not timestamp head migration files" do
- Dir.chdir(app_path) do
-
- app_file "db/migrate/1_one_migration.rb", <<-MIGRATION
- class OneMigration < ActiveRecord::Migration::Current
- end
- MIGRATION
+ app_file "db/migrate/1_one_migration.rb", <<-MIGRATION
+ class OneMigration < ActiveRecord::Migration::Current
+ end
+ MIGRATION
- app_file "db/migrate/02_two_migration.rb", <<-MIGRATION
- class TwoMigration < ActiveRecord::Migration::Current
- end
- MIGRATION
+ app_file "db/migrate/02_two_migration.rb", <<-MIGRATION
+ class TwoMigration < ActiveRecord::Migration::Current
+ end
+ MIGRATION
- `bin/rails db:migrate`
+ rails "db:migrate"
- output = `bin/rails db:migrate:status`
+ output = rails("db:migrate:status")
- assert_match(/up\s+001\s+One migration/, output)
- assert_match(/up\s+002\s+Two migration/, output)
- end
+ assert_match(/up\s+001\s+One migration/, output)
+ assert_match(/up\s+002\s+Two migration/, output)
end
test "schema generation when dump_schema_after_migration is set" do
add_to_config("config.active_record.dump_schema_after_migration = false")
Dir.chdir(app_path) do
- `bin/rails generate model book title:string`
- output = `bin/rails generate model author name:string`
+ rails "generate", "model", "book", "title:string"
+ output = rails("generate", "model", "author", "name:string")
version = output =~ %r{[^/]+db/migrate/(\d+)_create_authors\.rb} && $1
- `bin/rails db:migrate db:rollback db:forward db:migrate:up db:migrate:down VERSION=#{version}`
+ rails "db:migrate", "db:rollback", "db:forward", "db:migrate:up", "db:migrate:down", "VERSION=#{version}"
assert !File.exist?("db/schema.rb"), "should not dump schema when configured not to"
end
add_to_config("config.active_record.dump_schema_after_migration = true")
Dir.chdir(app_path) do
- `bin/rails generate model reviews book_id:integer`
- `bin/rails db:migrate`
+ rails "generate", "model", "reviews", "book_id:integer"
+ rails "db:migrate"
structure_dump = File.read("db/schema.rb")
assert_match(/create_table "reviews"/, structure_dump)
@@ -278,8 +413,8 @@ module ApplicationTests
test "default schema generation after migration" do
Dir.chdir(app_path) do
- `bin/rails generate model book title:string;
- bin/rails db:migrate`
+ rails "generate", "model", "book", "title:string"
+ rails "db:migrate"
structure_dump = File.read("db/schema.rb")
assert_match(/create_table "books"/, structure_dump)
@@ -288,12 +423,12 @@ module ApplicationTests
test "migration status migrated file is deleted" do
Dir.chdir(app_path) do
- `bin/rails generate model user username:string password:string;
- bin/rails generate migration add_email_to_users email:string;
- bin/rails db:migrate
- rm db/migrate/*email*.rb`
+ rails "generate", "model", "user", "username:string", "password:string"
+ rails "generate", "migration", "add_email_to_users", "email:string"
+ rails "db:migrate"
+ `rm db/migrate/*email*.rb`
- output = `bin/rails db:migrate:status`
+ output = rails("db:migrate:status")
assert_match(/up\s+\d{14}\s+Create users/, output)
assert_match(/up\s+\d{14}\s+\** NO FILE \**/, output)
diff --git a/railties/test/application/rake/notes_test.rb b/railties/test/application/rake/notes_test.rb
index e7ffea2e71..8e9fe9b6b4 100644
--- a/railties/test/application/rake/notes_test.rb
+++ b/railties/test/application/rake/notes_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
require "rails/source_annotation_extractor"
@@ -90,7 +92,8 @@ module ApplicationTests
test "custom rake task finds specific notes in specific directories" do
app_file "app/controllers/some_controller.rb", "# TODO: note in app directory"
- app_file "lib/some_file.rb", "# OPTIMIZE: note in lib directory\n" << "# FIXME: note in lib directory"
+ app_file "lib/some_file.rb", "# OPTIMIZE: note in lib directory\n" \
+ "# FIXME: note in lib directory"
app_file "test/some_test.rb", 1000.times.map { "" }.join("\n") << "# TODO: note in test directory"
app_file "lib/tasks/notes_custom.rake", <<-EOS
diff --git a/railties/test/application/rake/restart_test.rb b/railties/test/application/rake/restart_test.rb
index 6ebd2d5461..8614560bf2 100644
--- a/railties/test/application/rake/restart_test.rb
+++ b/railties/test/application/rake/restart_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
module ApplicationTests
@@ -15,12 +17,12 @@ module ApplicationTests
test "rails restart touches tmp/restart.txt" do
Dir.chdir(app_path) do
- `bin/rails restart`
+ rails "restart"
assert File.exist?("tmp/restart.txt")
prev_mtime = File.mtime("tmp/restart.txt")
sleep(1)
- `bin/rails restart`
+ rails "restart"
curr_mtime = File.mtime("tmp/restart.txt")
assert_not_equal prev_mtime, curr_mtime
end
@@ -29,19 +31,10 @@ module ApplicationTests
test "rails restart should work even if tmp folder does not exist" do
Dir.chdir(app_path) do
FileUtils.remove_dir("tmp")
- `bin/rails restart`
+ rails "restart"
assert File.exist?("tmp/restart.txt")
end
end
-
- test "rails restart removes server.pid also" do
- Dir.chdir(app_path) do
- FileUtils.mkdir_p("tmp/pids")
- FileUtils.touch("tmp/pids/server.pid")
- `bin/rails restart`
- assert_not File.exist?("tmp/pids/server.pid")
- end
- end
end
end
end
diff --git a/railties/test/application/rake/tmp_test.rb b/railties/test/application/rake/tmp_test.rb
new file mode 100644
index 0000000000..048fd7adcc
--- /dev/null
+++ b/railties/test/application/rake/tmp_test.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+require "isolation/abstract_unit"
+
+module ApplicationTests
+ module RakeTests
+ class TmpTest < ActiveSupport::TestCase
+ include ActiveSupport::Testing::Isolation
+
+ def setup
+ build_app
+ end
+
+ def teardown
+ teardown_app
+ end
+
+ test "tmp:clear clear cache, socket and screenshot files" do
+ Dir.chdir(app_path) do
+ FileUtils.mkdir_p("tmp/cache")
+ FileUtils.touch("tmp/cache/cache_file")
+
+ FileUtils.mkdir_p("tmp/sockets")
+ FileUtils.touch("tmp/sockets/socket_file")
+
+ FileUtils.mkdir_p("tmp/screenshots")
+ FileUtils.touch("tmp/screenshots/fail.png")
+
+ rails "tmp:clear"
+
+ assert_not File.exist?("tmp/cache/cache_file")
+ assert_not File.exist?("tmp/sockets/socket_file")
+ assert_not File.exist?("tmp/screenshots/fail.png")
+ end
+ end
+
+ test "tmp:clear should work if folder missing" do
+ FileUtils.remove_dir("#{app_path}/tmp")
+ rails "tmp:clear"
+ end
+ end
+ end
+end
diff --git a/railties/test/application/rake_test.rb b/railties/test/application/rake_test.rb
index 1b64a0a1ca..bf89098645 100644
--- a/railties/test/application/rake_test.rb
+++ b/railties/test/application/rake_test.rb
@@ -1,9 +1,12 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
+require "env_helpers"
require "active_support/core_ext/string/strip"
module ApplicationTests
class RakeTest < ActiveSupport::TestCase
- include ActiveSupport::Testing::Isolation
+ include ActiveSupport::Testing::Isolation, EnvHelpers
def setup
build_app
@@ -24,20 +27,20 @@ module ApplicationTests
end
test "task is protected when previous migration was production" do
- Dir.chdir(app_path) do
- output = `bin/rails generate model product name:string;
- env RAILS_ENV=production bin/rails db:create db:migrate;
- env RAILS_ENV=production bin/rails db:test:prepare test 2>&1`
+ with_rails_env "production" do
+ rails "generate", "model", "product", "name:string"
+ rails "db:create", "db:migrate"
+ output = rails("db:test:prepare", allow_failure: true)
assert_match(/ActiveRecord::ProtectedEnvironmentError/, output)
end
end
def test_not_protected_when_previous_migration_was_not_production
- Dir.chdir(app_path) do
- output = `bin/rails generate model product name:string;
- env RAILS_ENV=test bin/rails db:create db:migrate;
- env RAILS_ENV=test bin/rails db:test:prepare test 2>&1`
+ with_rails_env "test" do
+ rails "generate", "model", "product", "name:string"
+ rails "db:create", "db:migrate"
+ output = rails("db:test:prepare", "test")
refute_match(/ActiveRecord::ProtectedEnvironmentError/, output)
end
@@ -54,7 +57,7 @@ module ApplicationTests
Rails.application.initialize!
RUBY
- assert_match("SuperMiddleware", Dir.chdir(app_path) { `bin/rails middleware` })
+ assert_match("SuperMiddleware", rails("middleware"))
end
def test_initializers_are_executed_in_rake_tasks
@@ -69,7 +72,7 @@ module ApplicationTests
end
RUBY
- output = Dir.chdir(app_path) { `bin/rails do_nothing` }
+ output = rails("do_nothing")
assert_match "Doing something...", output
end
@@ -90,7 +93,7 @@ module ApplicationTests
end
RUBY
- output = Dir.chdir(app_path) { `bin/rails do_nothing` }
+ output = rails("do_nothing")
assert_match "Hello world", output
end
@@ -98,6 +101,7 @@ module ApplicationTests
add_to_config <<-RUBY
rake_tasks do
task do_nothing: :environment do
+ puts 'There is nothing'
end
end
RUBY
@@ -110,15 +114,13 @@ module ApplicationTests
raise 'should not be pre-required for rake even eager_load=true'
RUBY
- Dir.chdir(app_path) do
- assert system("bin/rails do_nothing RAILS_ENV=production"),
- "should not be pre-required for rake even eager_load=true"
- end
+ output = rails("do_nothing", "RAILS_ENV=production")
+ assert_match "There is nothing", output
end
def test_code_statistics_sanity
- assert_match "Code LOC: 26 Test LOC: 0 Code to Test Ratio: 1:0.0",
- Dir.chdir(app_path) { `bin/rails stats` }
+ assert_match "Code LOC: 25 Test LOC: 0 Code to Test Ratio: 1:0.0",
+ rails("stats")
end
def test_rails_routes_calls_the_route_inspector
@@ -128,8 +130,11 @@ module ApplicationTests
end
RUBY
- output = Dir.chdir(app_path) { `bin/rails routes` }
- assert_equal "Prefix Verb URI Pattern Controller#Action\n cart GET /cart(.:format) cart#show\n", output
+ output = rails("routes")
+ assert_equal <<-MESSAGE.strip_heredoc, output
+ Prefix Verb URI Pattern Controller#Action
+ cart GET /cart(.:format) cart#show
+ MESSAGE
end
def test_singular_resource_output_in_rake_routes
@@ -148,7 +153,7 @@ module ApplicationTests
" DELETE /post(.:format) posts#destroy",
" POST /post(.:format) posts#create\n"].join("\n")
- output = Dir.chdir(app_path) { `bin/rails routes -c PostController` }
+ output = rails("routes", "-c", "PostController")
assert_equal expected_output, output
end
@@ -161,13 +166,19 @@ module ApplicationTests
end
RUBY
- output = Dir.chdir(app_path) { `bin/rails routes -g show` }
- assert_equal "Prefix Verb URI Pattern Controller#Action\n cart GET /cart(.:format) cart#show\n", output
+ output = rails("routes", "-g", "show")
+ assert_equal <<-MESSAGE.strip_heredoc, output
+ Prefix Verb URI Pattern Controller#Action
+ cart GET /cart(.:format) cart#show
+ MESSAGE
- output = Dir.chdir(app_path) { `bin/rails routes -g POST` }
- assert_equal "Prefix Verb URI Pattern Controller#Action\n POST /cart(.:format) cart#create\n", output
+ output = rails("routes", "-g", "POST")
+ assert_equal <<-MESSAGE.strip_heredoc, output
+ Prefix Verb URI Pattern Controller#Action
+ POST /cart(.:format) cart#create
+ MESSAGE
- output = Dir.chdir(app_path) { `bin/rails routes -g basketballs` }
+ output = rails("routes", "-g", "basketballs")
assert_equal " Prefix Verb URI Pattern Controller#Action\n" \
"basketballs GET /basketballs(.:format) basketball#index\n", output
end
@@ -180,13 +191,13 @@ module ApplicationTests
end
RUBY
- output = Dir.chdir(app_path) { `bin/rails routes -c cart` }
+ output = rails("routes", "-c", "cart")
assert_equal "Prefix Verb URI Pattern Controller#Action\n cart GET /cart(.:format) cart#show\n", output
- output = Dir.chdir(app_path) { `bin/rails routes -c Cart` }
+ output = rails("routes", "-c", "Cart")
assert_equal "Prefix Verb URI Pattern Controller#Action\n cart GET /cart(.:format) cart#show\n", output
- output = Dir.chdir(app_path) { `bin/rails routes -c CartController` }
+ output = rails("routes", "-c", "CartController")
assert_equal "Prefix Verb URI Pattern Controller#Action\n cart GET /cart(.:format) cart#show\n", output
end
@@ -207,10 +218,10 @@ module ApplicationTests
" DELETE /admin/post(.:format) admin/posts#destroy",
" POST /admin/post(.:format) admin/posts#create\n"].join("\n")
- output = Dir.chdir(app_path) { `bin/rails routes -c Admin::PostController` }
+ output = rails("routes", "-c", "Admin::PostController")
assert_equal expected_output, output
- output = Dir.chdir(app_path) { `bin/rails routes -c PostController` }
+ output = rails("routes", "-c", "PostController")
assert_equal expected_output, output
end
@@ -220,7 +231,7 @@ module ApplicationTests
end
RUBY
- assert_equal <<-MESSAGE.strip_heredoc, Dir.chdir(app_path) { `bin/rails routes` }
+ assert_equal <<-MESSAGE.strip_heredoc, rails("routes")
You don't have any routes defined!
Please add some routes in config/routes.rb.
@@ -237,7 +248,11 @@ module ApplicationTests
RUBY
output = Dir.chdir(app_path) { `bin/rake --rakefile Rakefile routes` }
- assert_equal "Prefix Verb URI Pattern Controller#Action\n cart GET /cart(.:format) cart#show\n", output
+
+ assert_equal <<-MESSAGE.strip_heredoc, output
+ Prefix Verb URI Pattern Controller#Action
+ cart GET /cart(.:format) cart#show
+ MESSAGE
end
def test_logger_is_flushed_when_exiting_production_rake_tasks
@@ -249,44 +264,37 @@ module ApplicationTests
end
RUBY
- output = Dir.chdir(app_path) { `bin/rails log_something RAILS_ENV=production && cat log/production.log` }
- assert_match "Sample log message", output
+ rails "log_something", "RAILS_ENV=production"
+ assert_match "Sample log message", File.read("#{app_path}/log/production.log")
end
def test_loading_specific_fixtures
- Dir.chdir(app_path) do
- `bin/rails generate model user username:string password:string;
- bin/rails generate model product name:string;
- bin/rails db:migrate`
- end
+ rails "generate", "model", "user", "username:string", "password:string"
+ rails "generate", "model", "product", "name:string"
+ rails "db:migrate"
require "#{rails_root}/config/environment"
# loading a specific fixture
- errormsg = Dir.chdir(app_path) { `bin/rails db:fixtures:load FIXTURES=products` }
- assert $?.success?, errormsg
+ rails "db:fixtures:load", "FIXTURES=products"
assert_equal 2, ::AppTemplate::Application::Product.count
assert_equal 0, ::AppTemplate::Application::User.count
end
def test_loading_only_yml_fixtures
- Dir.chdir(app_path) do
- `bin/rails db:migrate`
- end
+ rails "db:migrate"
app_file "test/fixtures/products.csv", ""
require "#{rails_root}/config/environment"
- errormsg = Dir.chdir(app_path) { `bin/rails db:fixtures:load` }
- assert $?.success?, errormsg
+ rails "db:fixtures:load"
end
def test_scaffold_tests_pass_by_default
- output = Dir.chdir(app_path) do
- `bin/rails generate scaffold user username:string password:string;
- RAILS_ENV=test bin/rails db:migrate test`
- end
+ rails "generate", "scaffold", "user", "username:string", "password:string"
+ with_rails_env("test") { rails("db:migrate") }
+ output = rails("test")
assert_match(/7 runs, 9 assertions, 0 failures, 0 errors/, output)
assert_no_match(/Errors running/, output)
@@ -302,22 +310,20 @@ module ApplicationTests
end
RUBY
- output = Dir.chdir(app_path) do
- `bin/rails generate scaffold user username:string password:string;
- RAILS_ENV=test bin/rails db:migrate test`
- end
+ rails "generate", "scaffold", "user", "username:string", "password:string"
+ with_rails_env("test") { rails("db:migrate") }
+ output = rails("test")
assert_match(/5 runs, 7 assertions, 0 failures, 0 errors/, output)
assert_no_match(/Errors running/, output)
end
def test_scaffold_with_references_columns_tests_pass_by_default
- output = Dir.chdir(app_path) do
- `bin/rails generate model Product;
- bin/rails generate model Cart;
- bin/rails generate scaffold LineItems product:references cart:belongs_to;
- RAILS_ENV=test bin/rails db:migrate test`
- end
+ rails "generate", "model", "Product"
+ rails "generate", "model", "Cart"
+ rails "generate", "scaffold", "LineItems", "product:references", "cart:belongs_to"
+ with_rails_env("test") { rails("db:migrate") }
+ output = rails("test")
assert_match(/7 runs, 9 assertions, 0 failures, 0 errors/, output)
assert_no_match(/Errors running/, output)
@@ -325,59 +331,47 @@ module ApplicationTests
def test_db_test_prepare_when_using_sql_format
add_to_config "config.active_record.schema_format = :sql"
- output = Dir.chdir(app_path) do
- `bin/rails generate scaffold user username:string;
- bin/rails db:migrate;
- bin/rails db:test:prepare 2>&1 --trace`
- end
+ rails "generate", "scaffold", "user", "username:string"
+ rails "db:migrate"
+ output = rails("db:test:prepare", "--trace")
assert_match(/Execute db:test:load_structure/, output)
end
def test_rake_dump_structure_should_respect_db_structure_env_variable
- Dir.chdir(app_path) do
- # ensure we have a schema_migrations table to dump
- `bin/rails db:migrate db:structure:dump SCHEMA=db/my_structure.sql`
- end
+ # ensure we have a schema_migrations table to dump
+ rails "db:migrate", "db:structure:dump", "SCHEMA=db/my_structure.sql"
assert File.exist?(File.join(app_path, "db", "my_structure.sql"))
end
def test_rake_dump_structure_should_be_called_twice_when_migrate_redo
add_to_config "config.active_record.schema_format = :sql"
- output = Dir.chdir(app_path) do
- `bin/rails g model post title:string;
- bin/rails db:migrate:redo 2>&1 --trace;`
- end
+ rails "g", "model", "post", "title:string"
+ output = rails("db:migrate:redo", "--trace")
# expect only Invoke db:structure:dump (first_time)
assert_no_match(/^\*\* Invoke db:structure:dump\s+$/, output)
end
def test_rake_dump_schema_cache
- Dir.chdir(app_path) do
- `bin/rails generate model post title:string;
- bin/rails generate model product name:string;
- bin/rails db:migrate db:schema:cache:dump`
- end
+ rails "generate", "model", "post", "title:string"
+ rails "generate", "model", "product", "name:string"
+ rails "db:migrate", "db:schema:cache:dump"
assert File.exist?(File.join(app_path, "db", "schema_cache.yml"))
end
def test_rake_clear_schema_cache
- Dir.chdir(app_path) do
- `bin/rails db:schema:cache:dump db:schema:cache:clear`
- end
+ rails "db:schema:cache:dump", "db:schema:cache:clear"
assert !File.exist?(File.join(app_path, "db", "schema_cache.yml"))
end
def test_copy_templates
- Dir.chdir(app_path) do
- `bin/rails app:templates:copy`
- %w(controller mailer scaffold).each do |dir|
- assert File.exist?(File.join(app_path, "lib", "templates", "erb", dir))
- end
- %w(controller helper scaffold_controller assets).each do |dir|
- assert File.exist?(File.join(app_path, "lib", "templates", "rails", dir))
- end
+ rails "app:templates:copy"
+ %w(controller mailer scaffold).each do |dir|
+ assert File.exist?(File.join(app_path, "lib", "templates", "erb", dir))
+ end
+ %w(controller helper scaffold_controller assets).each do |dir|
+ assert File.exist?(File.join(app_path, "lib", "templates", "rails", dir))
end
end
@@ -385,18 +379,8 @@ module ApplicationTests
app_file "config/initializers/dummy.rb", "puts 'Hello, World!'"
app_file "template.rb", ""
- output = Dir.chdir(app_path) do
- `bin/rails app:template LOCATION=template.rb`
- end
-
+ output = rails("app:template", "LOCATION=template.rb")
assert_match(/Hello, World!/, output)
end
-
- def test_tmp_clear_should_work_if_folder_missing
- FileUtils.remove_dir("#{app_path}/tmp")
- errormsg = Dir.chdir(app_path) { `bin/rails tmp:clear` }
- assert_predicate $?, :success?
- assert_empty errormsg
- end
end
end
diff --git a/railties/test/application/rendering_test.rb b/railties/test/application/rendering_test.rb
index ccafc5b6f1..3724886c54 100644
--- a/railties/test/application/rendering_test.rb
+++ b/railties/test/application/rendering_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
require "rack/test"
diff --git a/railties/test/application/routing_test.rb b/railties/test/application/routing_test.rb
index 6742da20cc..bec038fb51 100644
--- a/railties/test/application/routing_test.rb
+++ b/railties/test/application/routing_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
require "rack/test"
@@ -293,7 +295,7 @@ module ApplicationTests
extend ActiveModel::Naming
include ActiveModel::Conversion
- def model_name
+ def self.model_name
@_model_name ||= ActiveModel::Name.new(self.class, nil, "User")
end
@@ -430,7 +432,7 @@ module ApplicationTests
extend ActiveModel::Naming
include ActiveModel::Conversion
- def model_name
+ def self.model_name
@_model_name ||= ActiveModel::Name.new(self.class, nil, "User")
end
@@ -542,7 +544,7 @@ module ApplicationTests
extend ActiveModel::Naming
include ActiveModel::Conversion
- def model_name
+ def self.model_name
@_model_name ||= ActiveModel::Name.new(self.class, nil, "User")
end
diff --git a/railties/test/application/runner_test.rb b/railties/test/application/runner_test.rb
index 0c45bc398a..aa5d495c97 100644
--- a/railties/test/application/runner_test.rb
+++ b/railties/test/application/runner_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
require "env_helpers"
@@ -24,22 +26,19 @@ module ApplicationTests
end
def test_should_include_runner_in_shebang_line_in_help_without_option
- assert_match "/rails runner", Dir.chdir(app_path) { `bin/rails runner` }
+ assert_match "/rails runner", rails("runner", allow_failure: true)
end
def test_should_include_runner_in_shebang_line_in_help
- assert_match "/rails runner", Dir.chdir(app_path) { `bin/rails runner --help` }
+ assert_match "/rails runner", rails("runner", "--help")
end
def test_should_run_ruby_statement
- assert_match "42", Dir.chdir(app_path) { `bin/rails runner "puts User.count"` }
+ assert_match "42", rails("runner", "puts User.count")
end
def test_should_set_argv_when_running_code
- output = Dir.chdir(app_path) {
- # Both long and short args, at start and end of ARGV
- `bin/rails runner "puts ARGV.join(',')" --foo a1 -b a2 a3 --moo`
- }
+ output = rails("runner", "puts ARGV.join(',')", "--foo", "a1", "-b", "a2", "a3", "--moo")
assert_equal "--foo,a1,-b,a2,a3,--moo", output.chomp
end
@@ -48,7 +47,7 @@ module ApplicationTests
puts User.count
SCRIPT
- assert_match "42", Dir.chdir(app_path) { `bin/rails runner "bin/count_users.rb"` }
+ assert_match "42", rails("runner", "bin/count_users.rb")
end
def test_no_minitest_loaded_in_production_mode
@@ -65,7 +64,7 @@ module ApplicationTests
puts $0
SCRIPT
- assert_match "bin/dollar0.rb", Dir.chdir(app_path) { `bin/rails runner "bin/dollar0.rb"` }
+ assert_match "bin/dollar0.rb", rails("runner", "bin/dollar0.rb")
end
def test_should_set_dollar_program_name_to_file
@@ -73,7 +72,7 @@ module ApplicationTests
puts $PROGRAM_NAME
SCRIPT
- assert_match "bin/program_name.rb", Dir.chdir(app_path) { `bin/rails runner "bin/program_name.rb"` }
+ assert_match "bin/program_name.rb", rails("runner", "bin/program_name.rb")
end
def test_passes_extra_args_to_file
@@ -81,7 +80,15 @@ module ApplicationTests
p ARGV
SCRIPT
- assert_match %w( a b ).to_s, Dir.chdir(app_path) { `bin/rails runner "bin/program_name.rb" a b` }
+ assert_match %w( a b ).to_s, rails("runner", "bin/program_name.rb", "a", "b")
+ end
+
+ def test_should_run_stdin
+ app_file "bin/count_users.rb", <<-SCRIPT
+ puts User.count
+ SCRIPT
+
+ assert_match "42", Dir.chdir(app_path) { `cat bin/count_users.rb | bin/rails runner -` }
end
def test_with_hook
@@ -91,35 +98,47 @@ module ApplicationTests
end
RUBY
- assert_match "true", Dir.chdir(app_path) { `bin/rails runner "puts Rails.application.config.ran"` }
+ assert_match "true", rails("runner", "puts Rails.application.config.ran")
end
def test_default_environment
- assert_match "development", Dir.chdir(app_path) { `bin/rails runner "puts Rails.env"` }
+ assert_match "development", rails("runner", "puts Rails.env")
end
def test_runner_detects_syntax_errors
- output = Dir.chdir(app_path) { `bin/rails runner "puts 'hello world" 2>&1` }
+ output = rails("runner", "puts 'hello world", allow_failure: true)
assert_not $?.success?
assert_match "unterminated string meets end of file", output
end
def test_runner_detects_bad_script_name
- output = Dir.chdir(app_path) { `bin/rails runner "iuiqwiourowe" 2>&1` }
+ output = rails("runner", "iuiqwiourowe", allow_failure: true)
assert_not $?.success?
assert_match "undefined local variable or method `iuiqwiourowe' for", output
end
def test_environment_with_rails_env
with_rails_env "production" do
- assert_match "production", Dir.chdir(app_path) { `bin/rails runner "puts Rails.env"` }
+ assert_match "production", rails("runner", "puts Rails.env")
end
end
def test_environment_with_rack_env
with_rack_env "production" do
- assert_match "production", Dir.chdir(app_path) { `bin/rails runner "puts Rails.env"` }
+ assert_match "production", rails("runner", "puts Rails.env")
end
end
+
+ def test_can_call_same_name_class_as_defined_in_thor
+ app_file "app/models/task.rb", <<-MODEL
+ class Task
+ def self.count
+ 42
+ end
+ end
+ MODEL
+
+ assert_match "42", rails("runner", "puts Task.count")
+ end
end
end
diff --git a/railties/test/application/server_test.rb b/railties/test/application/server_test.rb
new file mode 100644
index 0000000000..2238f4f63a
--- /dev/null
+++ b/railties/test/application/server_test.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+require "isolation/abstract_unit"
+require "console_helpers"
+require "rails/command"
+require "rails/commands/server/server_command"
+
+module ApplicationTests
+ class ServerTest < ActiveSupport::TestCase
+ include ActiveSupport::Testing::Isolation
+ include ConsoleHelpers
+
+ def setup
+ build_app
+ end
+
+ def teardown
+ teardown_app
+ end
+
+ test "deprecate support of older `config.ru`" do
+ remove_file "config.ru"
+ app_file "config.ru", <<-RUBY
+ require_relative 'config/environment'
+ run AppTemplate::Application
+ RUBY
+
+ server = Rails::Server.new(config: "#{app_path}/config.ru")
+ server.app
+
+ log = File.read(Rails.application.config.paths["log"].first)
+ assert_match(/DEPRECATION WARNING: Use `Rails::Application` subclass to start the server is deprecated/, log)
+ end
+
+ test "restart rails server with custom pid file path" do
+ skip "PTY unavailable" unless available_pty?
+
+ master, slave = PTY.open
+ pid = nil
+
+ begin
+ pid = Process.spawn("#{app_path}/bin/rails server -P tmp/dummy.pid", in: slave, out: slave, err: slave)
+ assert_output("Listening", master)
+
+ rails("restart")
+
+ assert_output("Restarting", master)
+ assert_output("Inherited", master)
+ ensure
+ kill(pid) if pid
+ end
+ end
+
+ private
+ def kill(pid)
+ Process.kill("TERM", pid)
+ Process.wait(pid)
+ rescue Errno::ESRCH
+ end
+ end
+end
diff --git a/railties/test/application/test_runner_test.rb b/railties/test/application/test_runner_test.rb
index 8e0712fca2..e92a0466dd 100644
--- a/railties/test/application/test_runner_test.rb
+++ b/railties/test/application/test_runner_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
require "active_support/core_ext/string/strip"
require "env_helpers"
@@ -16,13 +18,13 @@ module ApplicationTests
end
def test_run_via_backwardscompatibility
- require "rails/test_unit/minitest_plugin"
+ require "minitest/rails_plugin"
assert_nothing_raised do
Minitest.run_via[:ruby] = true
end
- assert_predicate Minitest.run_via, :ruby?
+ assert Minitest.run_via[:ruby]
end
def test_run_single_file
@@ -31,19 +33,33 @@ module ApplicationTests
assert_match "1 runs, 1 assertions, 0 failures", run_test_command("test/models/foo_test.rb")
end
+ def test_run_single_file_with_absolute_path
+ create_test_file :models, "foo"
+ create_test_file :models, "bar"
+ assert_match "1 runs, 1 assertions, 0 failures", run_test_command("#{app_path}/test/models/foo_test.rb")
+ end
+
def test_run_multiple_files
create_test_file :models, "foo"
create_test_file :models, "bar"
assert_match "2 runs, 2 assertions, 0 failures", run_test_command("test/models/foo_test.rb test/models/bar_test.rb")
end
+ def test_run_multiple_files_with_absolute_paths
+ create_test_file :models, "foo"
+ create_test_file :controllers, "foobar_controller"
+ create_test_file :models, "bar"
+
+ assert_match "2 runs, 2 assertions, 0 failures", run_test_command("#{app_path}/test/models/foo_test.rb #{app_path}/test/controllers/foobar_controller_test.rb")
+ end
+
def test_run_file_with_syntax_error
app_file "test/models/error_test.rb", <<-RUBY
require 'test_helper'
def; end
RUBY
- error = capture(:stderr) { run_test_command("test/models/error_test.rb") }
+ error = capture(:stderr) { run_test_command("test/models/error_test.rb", stderr: true) }
assert_match "syntax error", error
end
@@ -75,13 +91,11 @@ module ApplicationTests
create_test_file :unit, "baz_unit"
create_test_file :controllers, "foobar_controller"
- Dir.chdir(app_path) do
- `bin/rails test:units`.tap do |output|
- assert_match "FooTest", output
- assert_match "BarHelperTest", output
- assert_match "BazUnitTest", output
- assert_match "3 runs, 3 assertions, 0 failures", output
- end
+ rails("test:units").tap do |output|
+ assert_match "FooTest", output
+ assert_match "BarHelperTest", output
+ assert_match "BazUnitTest", output
+ assert_match "3 runs, 3 assertions, 0 failures", output
end
end
@@ -124,13 +138,11 @@ module ApplicationTests
create_test_file :functional, "baz_functional"
create_test_file :models, "foo"
- Dir.chdir(app_path) do
- `bin/rails test:functionals`.tap do |output|
- assert_match "FooMailerTest", output
- assert_match "BarControllerTest", output
- assert_match "BazFunctionalTest", output
- assert_match "3 runs, 3 assertions, 0 failures", output
- end
+ rails("test:functionals").tap do |output|
+ assert_match "FooMailerTest", output
+ assert_match "BarControllerTest", output
+ assert_match "BazFunctionalTest", output
+ assert_match "3 runs, 3 assertions, 0 failures", output
end
end
@@ -264,6 +276,18 @@ module ApplicationTests
end
end
+ def test_run_multiple_folders_with_absolute_paths
+ create_test_file :models, "account"
+ create_test_file :controllers, "accounts_controller"
+ create_test_file :helpers, "foo_helper"
+
+ run_test_command("#{app_path}/test/models #{app_path}/test/controllers").tap do |output|
+ assert_match "AccountTest", output
+ assert_match "AccountsControllerTest", output
+ assert_match "2 runs, 2 assertions, 0 failures, 0 errors, 0 skips", output
+ end
+ end
+
def test_run_with_ruby_command
app_file "test/models/post_test.rb", <<-RUBY
require 'test_helper'
@@ -489,18 +513,18 @@ module ApplicationTests
create_test_file :models, "post", pass: false
output = run_test_command("test/models/post_test.rb")
- assert_match %r{Finished in.*\n\n1 runs, 1 assertions}, output
+ assert_match %r{Finished in.*\n1 runs, 1 assertions}, output
end
def test_fail_fast
create_test_file :models, "post", pass: false
assert_match(/Interrupt/,
- capture(:stderr) { run_test_command("test/models/post_test.rb --fail-fast") })
+ capture(:stderr) { run_test_command("test/models/post_test.rb --fail-fast", stderr: true) })
end
def test_raise_error_when_specified_file_does_not_exist
- error = capture(:stderr) { run_test_command("test/not_exists.rb") }
+ error = capture(:stderr) { run_test_command("test/not_exists.rb", stderr: true) }
assert_match(%r{cannot load such file.+test/not_exists\.rb}, error)
end
@@ -526,14 +550,16 @@ module ApplicationTests
def test_rails_db_create_all_restores_db_connection
create_test_file :models, "account"
- output = Dir.chdir(app_path) { `bin/rails db:create:all db:migrate && echo ".tables" | rails dbconsole` }
+ rails "db:create:all", "db:migrate"
+ output = Dir.chdir(app_path) { `echo ".tables" | rails dbconsole` }
assert_match "ar_internal_metadata", output, "tables should be dumped"
end
def test_rails_db_create_all_restores_db_connection_after_drop
create_test_file :models, "account"
- Dir.chdir(app_path) { `bin/rails db:create:all` } # create all to avoid warnings
- output = Dir.chdir(app_path) { `bin/rails db:drop:all db:create:all db:migrate && echo ".tables" | rails dbconsole` }
+ rails "db:create:all" # create all to avoid warnings
+ rails "db:drop:all", "db:create:all", "db:migrate"
+ output = Dir.chdir(app_path) { `echo ".tables" | rails dbconsole` }
assert_match "ar_internal_metadata", output, "tables should be dumped"
end
@@ -573,7 +599,7 @@ module ApplicationTests
end
RUBY
assert_match(/warning: assigned but unused variable/,
- capture(:stderr) { run_test_command("test/models/warnings_test.rb -w") })
+ capture(:stderr) { run_test_command("test/models/warnings_test.rb -w", stderr: true) })
end
def test_reset_sessions_before_rollback_on_system_tests
@@ -651,12 +677,12 @@ module ApplicationTests
end
private
- def run_test_command(arguments = "test/unit/test_test.rb")
- Dir.chdir(app_path) { `bin/rails t #{arguments}` }
+ def run_test_command(arguments = "test/unit/test_test.rb", **opts)
+ rails "t", *Shellwords.split(arguments), allow_failure: true, **opts
end
def create_model_with_fixture
- script "generate model user name:string"
+ rails "generate", "model", "user", "name:string"
app_file "test/fixtures/users.yml", <<-YAML.strip_heredoc
vampire:
@@ -727,17 +753,17 @@ module ApplicationTests
end
def create_scaffold
- script "generate scaffold user name:string"
- Dir.chdir(app_path) { File.exist?("app/models/user.rb") }
+ rails "generate", "scaffold", "user", "name:string"
+ assert File.exist?("#{app_path}/app/models/user.rb")
run_migration
end
def create_controller
- script "generate controller admin/dashboard index"
+ rails "generate", "controller", "admin/dashboard", "index"
end
def run_migration
- Dir.chdir(app_path) { `bin/rails db:migrate` }
+ rails "db:migrate"
end
end
end
diff --git a/railties/test/application/test_test.rb b/railties/test/application/test_test.rb
index 32d2a6857c..0a51e98656 100644
--- a/railties/test/application/test_test.rb
+++ b/railties/test/application/test_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
module ApplicationTests
@@ -55,7 +57,7 @@ module ApplicationTests
end
RUBY
- assert_unsuccessful_run "unit/foo_test.rb", "Failed assertion"
+ assert_unsuccessful_run "unit/foo_test.rb", "Failure:\nFooTest#test_truth"
end
test "integration test" do
@@ -100,7 +102,7 @@ module ApplicationTests
end
test "ruby schema migrations" do
- output = script("generate model user name:string")
+ output = rails("generate", "model", "user", "name:string")
version = output.match(/(\d+)_create_users\.rb/)[1]
app_file "test/models/user_test.rb", <<-RUBY
@@ -137,7 +139,7 @@ module ApplicationTests
end
test "sql structure migrations" do
- output = script("generate model user name:string")
+ output = rails("generate", "model", "user", "name:string")
version = output.match(/(\d+)_create_users\.rb/)[1]
app_file "test/models/user_test.rb", <<-RUBY
@@ -176,7 +178,7 @@ module ApplicationTests
end
test "sql structure migrations when adding column to existing table" do
- output_1 = script("generate model user name:string")
+ output_1 = rails("generate", "model", "user", "name:string")
version_1 = output_1.match(/(\d+)_create_users\.rb/)[1]
app_file "test/models/user_test.rb", <<-RUBY
@@ -201,7 +203,7 @@ module ApplicationTests
assert_successful_test_run("models/user_test.rb")
- output_2 = script("generate migration add_email_to_users")
+ output_2 = rails("generate", "migration", "add_email_to_users")
version_2 = output_2.match(/(\d+)_add_email_to_users\.rb/)[1]
app_file "test/models/user_test.rb", <<-RUBY
@@ -229,7 +231,7 @@ module ApplicationTests
# For now, the user has to synchronize the schema manually.
# This test-case serves as a reminder for this use-case.
test "manually synchronize test schema after rollback" do
- output = script("generate model user name:string")
+ output = rails("generate", "model", "user", "name:string")
version = output.match(/(\d+)_create_users\.rb/)[1]
app_file "test/models/user_test.rb", <<-RUBY
@@ -263,7 +265,7 @@ module ApplicationTests
assert_successful_test_run "models/user_test.rb"
- Dir.chdir(app_path) { `bin/rails db:test:prepare` }
+ rails "db:test:prepare"
assert_unsuccessful_run "models/user_test.rb", <<-ASSERTION
Expected: ["id", "name"]
@@ -272,7 +274,7 @@ Expected: ["id", "name"]
end
test "hooks for plugins" do
- output = script("generate model user name:string")
+ output = rails("generate", "model", "user", "name:string")
version = output.match(/(\d+)_create_users\.rb/)[1]
app_file "lib/tasks/hooks.rake", <<-RUBY
@@ -332,7 +334,7 @@ Expected: ["id", "name"]
end
def run_test_file(name, options = {})
- Dir.chdir(app_path) { `bin/rails test "#{app_path}/test/#{name}" 2>&1` }
+ rails "test", "#{app_path}/test/#{name}", allow_failure: true
end
end
end
diff --git a/railties/test/application/url_generation_test.rb b/railties/test/application/url_generation_test.rb
index 37f129475c..f22b9fda3d 100644
--- a/railties/test/application/url_generation_test.rb
+++ b/railties/test/application/url_generation_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
module ApplicationTests
@@ -14,7 +16,6 @@ module ApplicationTests
require "action_view/railtie"
class MyApp < Rails::Application
- secrets.secret_key_base = "3b7cd727ee24e8444053437c36cc66c4"
config.session_store :cookie_store, key: "_myapp_session"
config.active_support.deprecation = :log
config.eager_load = false
diff --git a/railties/test/application/version_test.rb b/railties/test/application/version_test.rb
index 6b419ae7ae..ae85cf8f05 100644
--- a/railties/test/application/version_test.rb
+++ b/railties/test/application/version_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
require "rails/gem_version"
@@ -13,12 +15,12 @@ class VersionTest < ActiveSupport::TestCase
end
test "command works" do
- output = Dir.chdir(app_path) { `bin/rails version` }
+ output = rails("version")
assert_equal "Rails #{Rails.gem_version}\n", output
end
test "short-cut alias works" do
- output = Dir.chdir(app_path) { `bin/rails -v` }
+ output = rails("-v")
assert_equal "Rails #{Rails.gem_version}\n", output
end
end
diff --git a/railties/test/backtrace_cleaner_test.rb b/railties/test/backtrace_cleaner_test.rb
index f71e56f323..70917ba20b 100644
--- a/railties/test/backtrace_cleaner_test.rb
+++ b/railties/test/backtrace_cleaner_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "abstract_unit"
require "rails/backtrace_cleaner"
diff --git a/railties/test/code_statistics_calculator_test.rb b/railties/test/code_statistics_calculator_test.rb
index 25a8a40d27..51917de2e0 100644
--- a/railties/test/code_statistics_calculator_test.rb
+++ b/railties/test/code_statistics_calculator_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "abstract_unit"
require "rails/code_statistics_calculator"
diff --git a/railties/test/code_statistics_test.rb b/railties/test/code_statistics_test.rb
index e6e3943117..7ad1ac3094 100644
--- a/railties/test/code_statistics_test.rb
+++ b/railties/test/code_statistics_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "abstract_unit"
require "rails/code_statistics"
diff --git a/railties/test/command/base_test.rb b/railties/test/command/base_test.rb
index ebfc4d0ba9..a49ae8aae7 100644
--- a/railties/test/command/base_test.rb
+++ b/railties/test/command/base_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "abstract_unit"
require "rails/command"
require "rails/commands/generate/generate_command"
@@ -6,6 +8,6 @@ require "rails/commands/secrets/secrets_command"
class Rails::Command::BaseTest < ActiveSupport::TestCase
test "printing commands" do
assert_equal %w(generate), Rails::Command::GenerateCommand.printing_commands
- assert_equal %w(secrets:setup secrets:edit), Rails::Command::SecretsCommand.printing_commands
+ assert_equal %w(secrets:setup secrets:edit secrets:show), Rails::Command::SecretsCommand.printing_commands
end
end
diff --git a/railties/test/commands/console_test.rb b/railties/test/commands/console_test.rb
index 4fc082e4ca..45ab8d87ff 100644
--- a/railties/test/commands/console_test.rb
+++ b/railties/test/commands/console_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "abstract_unit"
require "env_helpers"
require "rails/command"
@@ -47,7 +49,7 @@ class Rails::ConsoleTest < ActiveSupport::TestCase
end
def test_console_with_environment
- start ["-e production"]
+ start ["-e", "production"]
assert_match(/\sproduction\s/, output)
end
@@ -82,24 +84,35 @@ class Rails::ConsoleTest < ActiveSupport::TestCase
assert_match(/\sspecial-production\s/, output)
end
+ def test_e_option_is_properly_expanded
+ start ["-e", "prod"]
+ assert_match(/\sproduction\s/, output)
+ end
+
def test_environment_option
start ["--environment=special-production"]
assert_match(/\sspecial-production\s/, output)
end
def test_rails_env_is_production_when_first_argument_is_p
- start ["p"]
- assert_match(/\sproduction\s/, output)
+ assert_deprecated do
+ start ["p"]
+ assert_match(/\sproduction\s/, output)
+ end
end
def test_rails_env_is_test_when_first_argument_is_t
- start ["t"]
- assert_match(/\stest\s/, output)
+ assert_deprecated do
+ start ["t"]
+ assert_match(/\stest\s/, output)
+ end
end
def test_rails_env_is_development_when_argument_is_d
- start ["d"]
- assert_match(/\sdevelopment\s/, output)
+ assert_deprecated do
+ start ["d"]
+ assert_match(/\sdevelopment\s/, output)
+ end
end
def test_rails_env_is_dev_when_argument_is_dev_and_dev_env_is_present
@@ -111,7 +124,9 @@ class Rails::ConsoleTest < ActiveSupport::TestCase
end
end
- assert_match("dev", parse_arguments(["dev"])[:environment])
+ assert_deprecated do
+ assert_match("dev", parse_arguments(["dev"])[:environment])
+ end
ensure
Rails::Command::ConsoleCommand.class_eval do
undef_method :available_environments
@@ -157,21 +172,8 @@ class Rails::ConsoleTest < ActiveSupport::TestCase
end
def parse_arguments(args)
- Rails::Command::ConsoleCommand.class_eval do
- alias_method :old_perform, :perform
- define_method(:perform) do
- extract_environment_option_from_argument
-
- options
- end
- end
-
- Rails::Command.invoke(:console, args)
- ensure
- Rails::Command::ConsoleCommand.class_eval do
- undef_method :perform
- alias_method :perform, :old_perform
- undef_method :old_perform
- end
+ command = Rails::Command::ConsoleCommand.new([], args)
+ command.send(:extract_environment_option_from_argument)
+ command.options
end
end
diff --git a/railties/test/commands/credentials_test.rb b/railties/test/commands/credentials_test.rb
new file mode 100644
index 0000000000..4ef827fcf1
--- /dev/null
+++ b/railties/test/commands/credentials_test.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+require "isolation/abstract_unit"
+require "env_helpers"
+require "rails/command"
+require "rails/commands/credentials/credentials_command"
+
+class Rails::Command::CredentialsCommandTest < ActiveSupport::TestCase
+ include ActiveSupport::Testing::Isolation, EnvHelpers
+
+ setup { build_app }
+
+ teardown { teardown_app }
+
+ test "edit without editor gives hint" do
+ run_edit_command(editor: "").tap do |output|
+ assert_match "No $EDITOR to open file in", output
+ assert_match "bin/rails credentials:edit", output
+ end
+ end
+
+ test "edit credentials" do
+ # Run twice to ensure credentials can be reread after first edit pass.
+ 2.times do
+ assert_match(/access_key_id: 123/, run_edit_command)
+ end
+ end
+
+ test "show credentials" do
+ assert_match(/access_key_id: 123/, run_show_command)
+ end
+
+ test "edit command does not add master key to gitignore when already exist" do
+ run_edit_command
+
+ Dir.chdir(app_path) do
+ gitignore = File.read(".gitignore")
+ assert_equal 1, gitignore.scan(%r|config/master\.key|).length
+ end
+ end
+
+ private
+ def run_edit_command(editor: "cat")
+ switch_env("EDITOR", editor) do
+ rails "credentials:edit"
+ end
+ end
+
+ def run_show_command
+ rails "credentials:show"
+ end
+end
diff --git a/railties/test/commands/dbconsole_test.rb b/railties/test/commands/dbconsole_test.rb
index 0f8c5dbb79..6ad96b28c7 100644
--- a/railties/test/commands/dbconsole_test.rb
+++ b/railties/test/commands/dbconsole_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "abstract_unit"
require "minitest/mock"
require "rails/command"
@@ -98,14 +100,24 @@ class Rails::DBConsoleTest < ActiveSupport::TestCase
end
def test_rails_env_is_development_when_argument_is_dev
+ assert_deprecated do
+ stub_available_environments([ "development", "test" ]) do
+ assert_match("development", parse_arguments([ "dev" ])[:environment])
+ end
+ end
+ end
+
+ def test_rails_env_is_development_when_environment_option_is_dev
stub_available_environments([ "development", "test" ]) do
- assert_match("development", parse_arguments([ "dev" ])[:environment])
+ assert_match("development", parse_arguments([ "-e", "dev" ])[:environment])
end
end
def test_rails_env_is_dev_when_argument_is_dev_and_dev_env_is_present
- stub_available_environments([ "dev" ]) do
- assert_match("dev", parse_arguments([ "dev" ])[:environment])
+ assert_deprecated do
+ stub_available_environments([ "dev" ]) do
+ assert_match("dev", parse_arguments([ "dev" ])[:environment])
+ end
end
end
@@ -194,12 +206,61 @@ class Rails::DBConsoleTest < ActiveSupport::TestCase
assert_equal ["sqlplus", "user/secret@db"], dbconsole.find_cmd_and_exec_args
end
+ def test_sqlserver
+ start(adapter: "sqlserver", database: "db", username: "user", password: "secret", host: "localhost", port: 1433)
+ assert_not aborted
+ assert_equal ["sqsh", "-D", "db", "-U", "user", "-P", "secret", "-S", "localhost:1433"], dbconsole.find_cmd_and_exec_args
+ end
+
def test_unknown_command_line_client
start(adapter: "unknown", database: "db")
assert aborted
assert_match(/Unknown command-line client for db/, output)
end
+ def test_primary_is_automatically_picked_with_3_level_configuration
+ sample_config = {
+ "test" => {
+ "primary" => {
+ "adapter" => "postgresql"
+ }
+ }
+ }
+
+ app_db_config(sample_config) do
+ assert_equal "postgresql", Rails::DBConsole.new.config["adapter"]
+ end
+ end
+
+ def test_specifying_a_custom_connection_and_environment
+ stub_available_environments(["development"]) do
+ dbconsole = parse_arguments(["-c", "custom", "-e", "development"])
+
+ assert_equal "development", dbconsole[:environment]
+ assert_equal "custom", dbconsole.connection
+ end
+ end
+
+ def test_specifying_a_missing_connection
+ app_db_config({}) do
+ e = assert_raises(ActiveRecord::AdapterNotSpecified) do
+ Rails::Command.invoke(:dbconsole, ["-c", "i_do_not_exist"])
+ end
+
+ assert_includes e.message, "'i_do_not_exist' connection is not configured."
+ end
+ end
+
+ def test_specifying_a_missing_environment
+ app_db_config({}) do
+ e = assert_raises(ActiveRecord::AdapterNotSpecified) do
+ Rails::Command.invoke(:dbconsole)
+ end
+
+ assert_includes e.message, "'test' database is not configured."
+ end
+ end
+
def test_print_help_short
stdout = capture(:stdout) do
Rails::Command.invoke(:dbconsole, ["-h"])
diff --git a/railties/test/commands/encrypted_test.rb b/railties/test/commands/encrypted_test.rb
new file mode 100644
index 0000000000..0461493f2a
--- /dev/null
+++ b/railties/test/commands/encrypted_test.rb
@@ -0,0 +1,80 @@
+# frozen_string_literal: true
+
+require "isolation/abstract_unit"
+require "env_helpers"
+require "rails/command"
+require "rails/commands/encrypted/encrypted_command"
+
+class Rails::Command::EncryptedCommandTest < ActiveSupport::TestCase
+ include ActiveSupport::Testing::Isolation, EnvHelpers
+
+ setup :build_app
+ teardown :teardown_app
+
+ test "edit without editor gives hint" do
+ run_edit_command("config/tokens.yml.enc", editor: "").tap do |output|
+ assert_match "No $EDITOR to open file in", output
+ assert_match "bin/rails encrypted:edit", output
+ end
+ end
+
+ test "edit encrypted file" do
+ # Run twice to ensure file can be reread after first edit pass.
+ 2.times do
+ assert_match(/access_key_id: 123/, run_edit_command("config/tokens.yml.enc"))
+ end
+ end
+
+ test "edit command does not add master key to gitignore when already exist" do
+ run_edit_command("config/tokens.yml.enc")
+
+ Dir.chdir(app_path) do
+ assert_match "/config/master.key", File.read(".gitignore")
+ end
+ end
+
+ test "edit encrypts file with custom key" do
+ run_edit_command("config/tokens.yml.enc", key: "config/tokens.key")
+
+ Dir.chdir(app_path) do
+ assert File.exist?("config/tokens.yml.enc")
+ assert File.exist?("config/tokens.key")
+
+ assert_match "/config/tokens.key", File.read(".gitignore")
+ end
+
+ assert_match(/access_key_id: 123/, run_edit_command("config/tokens.yml.enc", key: "config/tokens.key"))
+ end
+
+ test "show encrypted file with custom key" do
+ run_edit_command("config/tokens.yml.enc", key: "config/tokens.key")
+
+ assert_match(/access_key_id: 123/, run_show_command("config/tokens.yml.enc", key: "config/tokens.key"))
+ end
+
+ test "won't corrupt encrypted file when passed wrong key" do
+ run_edit_command("config/tokens.yml.enc", key: "config/tokens.key")
+
+ assert_match "passed the wrong key",
+ run_edit_command("config/tokens.yml.enc", allow_failure: true)
+
+ assert_match(/access_key_id: 123/, run_show_command("config/tokens.yml.enc", key: "config/tokens.key"))
+ end
+
+ private
+ def run_edit_command(file, key: nil, editor: "cat", **options)
+ switch_env("EDITOR", editor) do
+ rails "encrypted:edit", prepare_args(file, key), **options
+ end
+ end
+
+ def run_show_command(file, key: nil)
+ rails "encrypted:show", prepare_args(file, key)
+ end
+
+ def prepare_args(file, key)
+ args = [ file ]
+ args.push("--key", key) if key
+ args
+ end
+end
diff --git a/railties/test/commands/secrets_test.rb b/railties/test/commands/secrets_test.rb
index be610f3b47..6b9f284a0c 100644
--- a/railties/test/commands/secrets_test.rb
+++ b/railties/test/commands/secrets_test.rb
@@ -1,25 +1,45 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
+require "env_helpers"
require "rails/command"
require "rails/commands/secrets/secrets_command"
class Rails::Command::SecretsCommandTest < ActiveSupport::TestCase
- include ActiveSupport::Testing::Isolation
+ include ActiveSupport::Testing::Isolation, EnvHelpers
+
+ setup :build_app
+ teardown :teardown_app
- def setup
- build_app
+ test "edit without editor gives hint" do
+ assert_match "No $EDITOR to open decrypted secrets in", run_edit_command(editor: "")
end
- def teardown
- teardown_app
+ test "encrypted secrets are deprecated when using credentials" do
+ assert_match "Encrypted secrets is deprecated", run_setup_command
+ assert_equal 1, $?.exitstatus
+ assert_not File.exist?("config/secrets.yml.enc")
end
- test "edit without editor gives hint" do
- assert_match "No $EDITOR to open decrypted secrets in", run_edit_command(editor: "")
+ test "encrypted secrets are deprecated when running edit without setup" do
+ assert_match "Encrypted secrets is deprecated", run_setup_command
+ assert_equal 1, $?.exitstatus
+ assert_not File.exist?("config/secrets.yml.enc")
+ end
+
+ test "encrypted secrets are deprecated for 5.1 config/secrets.yml apps" do
+ Dir.chdir(app_path) do
+ FileUtils.rm("config/credentials.yml.enc")
+ FileUtils.touch("config/secrets.yml")
+
+ assert_match "Encrypted secrets is deprecated", run_setup_command
+ assert_equal 1, $?.exitstatus
+ assert_not File.exist?("config/secrets.yml.enc")
+ end
end
test "edit secrets" do
- # Runs setup before first edit.
- assert_match(/Adding config\/secrets\.yml\.key to store the encryption key/, run_edit_command)
+ prevent_deprecation
# Run twice to ensure encrypted secrets can be reread after first edit pass.
2.times do
@@ -27,8 +47,31 @@ class Rails::Command::SecretsCommandTest < ActiveSupport::TestCase
end
end
+ test "show secrets" do
+ prevent_deprecation
+
+ assert_match(/external_api_key: 1466aac22e6a869134be3d09b9e89232fc2c2289/, run_show_command)
+ end
+
private
+ def prevent_deprecation
+ Dir.chdir(app_path) do
+ File.write("config/secrets.yml.key", "f731758c639da2604dfb6bf3d1025de8")
+ File.write("config/secrets.yml.enc", "sEB0mHxDbeP1/KdnMk00wyzPFACl9K6t0cZWn5/Mfx/YbTHvnI07vrneqHg9kaH3wOS7L6pIQteu1P077OtE4BSx/ZRc/sgQPHyWu/tXsrfHqnPNpayOF/XZqizE91JacSFItNMWpuPsp9ynbzz+7cGhoB1S4aPNIU6u0doMrzdngDbijsaAFJmsHIQh6t/QHoJx--8aMoE0PvUWmw1Iqz--ldFqnM/K0g9k17M8PKoN/Q==")
+ end
+ end
+
def run_edit_command(editor: "cat")
- Dir.chdir(app_path) { `EDITOR="#{editor}" bin/rails secrets:edit` }
+ switch_env("EDITOR", editor) do
+ rails "secrets:edit", allow_failure: true
+ end
+ end
+
+ def run_show_command
+ rails "secrets:show", allow_failure: true
+ end
+
+ def run_setup_command
+ rails "secrets:setup", allow_failure: true
end
end
diff --git a/railties/test/commands/server_test.rb b/railties/test/commands/server_test.rb
index 722323efdc..33715ea75f 100644
--- a/railties/test/commands/server_test.rb
+++ b/railties/test/commands/server_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "abstract_unit"
require "env_helpers"
require "rails/command"
@@ -20,6 +22,18 @@ class Rails::ServerTest < ActiveSupport::TestCase
assert_nil options[:server]
end
+ def test_daemon_with_option
+ args = ["-d"]
+ options = parse_arguments(args)
+ assert_equal true, options[:daemonize]
+ end
+
+ def test_daemon_without_option
+ args = []
+ options = parse_arguments(args)
+ assert_equal false, options[:daemonize]
+ end
+
def test_server_option_without_environment
args = ["thin"]
with_rack_env nil do
@@ -79,6 +93,18 @@ class Rails::ServerTest < ActiveSupport::TestCase
assert_equal false, options[:caching]
end
+ def test_early_hints_with_option
+ args = ["--early-hints"]
+ options = parse_arguments(args)
+ assert_equal true, options[:early_hints]
+ end
+
+ def test_early_hints_is_nil_by_default
+ args = []
+ options = parse_arguments(args)
+ assert_nil options[:early_hints]
+ end
+
def test_log_stdout
with_rack_env nil do
with_rails_env nil do
@@ -188,7 +214,7 @@ class Rails::ServerTest < ActiveSupport::TestCase
ARGV.replace args
options = parse_arguments(args)
- expected = "bin/rails server -p 4567 -b 127.0.0.1 -c dummy_config.ru -d -e test -P tmp/server.pid -C"
+ expected = "bin/rails server -p 4567 -b 127.0.0.1 -c dummy_config.ru -d -e test -P tmp/server.pid -C --restart"
assert_equal expected, options[:restart_cmd]
ensure
diff --git a/railties/test/configuration/middleware_stack_proxy_test.rb b/railties/test/configuration/middleware_stack_proxy_test.rb
index 559ce72693..bc72b7f0c9 100644
--- a/railties/test/configuration/middleware_stack_proxy_test.rb
+++ b/railties/test/configuration/middleware_stack_proxy_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "active_support"
require "active_support/testing/autorun"
require "rails/configuration"
diff --git a/railties/test/console_helpers.rb b/railties/test/console_helpers.rb
new file mode 100644
index 0000000000..8350fce5ee
--- /dev/null
+++ b/railties/test/console_helpers.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+begin
+ require "pty"
+rescue LoadError
+end
+
+module ConsoleHelpers
+ def assert_output(expected, io, timeout = 10)
+ timeout = Time.now + timeout
+
+ output = "".dup
+ until output.include?(expected) || Time.now > timeout
+ if IO.select([io], [], [], 0.1)
+ output << io.read(1)
+ end
+ end
+
+ assert_includes output, expected, "#{expected.inspect} expected, but got:\n\n#{output}"
+ end
+
+ def available_pty?
+ defined?(PTY) && PTY.respond_to?(:open)
+ end
+end
diff --git a/railties/test/engine/commands_test.rb b/railties/test/engine/commands_test.rb
index b1c937143f..aeb64d445b 100644
--- a/railties/test/engine/commands_test.rb
+++ b/railties/test/engine/commands_test.rb
@@ -1,10 +1,11 @@
+# frozen_string_literal: true
+
require "abstract_unit"
-begin
- require "pty"
-rescue LoadError
-end
+require "console_helpers"
class Rails::Engine::CommandsTest < ActiveSupport::TestCase
+ include ConsoleHelpers
+
def setup
@destination_root = Dir.mktmpdir("bukkits")
Dir.chdir(@destination_root) { `bundle exec rails plugin new bukkits --mountable` }
@@ -64,19 +65,6 @@ class Rails::Engine::CommandsTest < ActiveSupport::TestCase
"#{@destination_root}/bukkits"
end
- def assert_output(expected, io, timeout = 10)
- timeout = Time.now + timeout
-
- output = ""
- until output.include?(expected) || Time.now > timeout
- if IO.select([io], [], [], 0.1)
- output << io.read(1)
- end
- end
-
- assert_includes output, expected, "#{expected.inspect} expected, but got:\n\n#{output}"
- end
-
def spawn_command(command, fd)
Process.spawn(
"#{plugin_path}/bin/rails #{command}",
@@ -84,10 +72,6 @@ class Rails::Engine::CommandsTest < ActiveSupport::TestCase
)
end
- def available_pty?
- defined?(PTY) && PTY.respond_to?(:open)
- end
-
def kill(pid)
Process.kill("TERM", pid)
Process.wait(pid)
diff --git a/railties/test/engine/test_test.rb b/railties/test/engine/test_test.rb
new file mode 100644
index 0000000000..18af85a0aa
--- /dev/null
+++ b/railties/test/engine/test_test.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require "abstract_unit"
+
+class Rails::Engine::TestTest < ActiveSupport::TestCase
+ setup do
+ @destination_root = Dir.mktmpdir("bukkits")
+ Dir.chdir(@destination_root) { `bundle exec rails plugin new bukkits --mountable` }
+ end
+
+ teardown do
+ FileUtils.rm_rf(@destination_root)
+ end
+
+ test "automatically synchronize test schema" do
+ Dir.chdir(plugin_path) do
+ # In order to confirm that migration files are loaded, generate multiple migration files.
+ `bin/rails generate model user name:string;
+ bin/rails generate model todo name:string;
+ RAILS_ENV=development bin/rails db:migrate`
+
+ output = `bin/rails test test/models/bukkits/user_test.rb`
+ assert_includes(output, "0 runs, 0 assertions, 0 failures, 0 errors, 0 skips")
+ end
+ end
+
+ private
+ def plugin_path
+ "#{@destination_root}/bukkits"
+ end
+end
diff --git a/railties/test/engine_test.rb b/railties/test/engine_test.rb
index 248afa2d2c..4bd8a07085 100644
--- a/railties/test/engine_test.rb
+++ b/railties/test/engine_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "abstract_unit"
class EngineTest < ActiveSupport::TestCase
diff --git a/railties/test/env_helpers.rb b/railties/test/env_helpers.rb
index 1f64d5fda3..336832b867 100644
--- a/railties/test/env_helpers.rb
+++ b/railties/test/env_helpers.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rails"
module EnvHelpers
diff --git a/railties/test/fixtures/about_yml_plugins/bad_about_yml/about.yml b/railties/test/fixtures/about_yml_plugins/bad_about_yml/about.yml
deleted file mode 100644
index fe80872a16..0000000000
--- a/railties/test/fixtures/about_yml_plugins/bad_about_yml/about.yml
+++ /dev/null
@@ -1 +0,0 @@
-# an empty YAML file - any content in here seems to get parsed as a string \ No newline at end of file
diff --git a/railties/test/fixtures/about_yml_plugins/bad_about_yml/init.rb b/railties/test/fixtures/about_yml_plugins/bad_about_yml/init.rb
deleted file mode 100644
index 636bc1a8ab..0000000000
--- a/railties/test/fixtures/about_yml_plugins/bad_about_yml/init.rb
+++ /dev/null
@@ -1 +0,0 @@
-# intentionally empty
diff --git a/railties/test/fixtures/about_yml_plugins/plugin_without_about_yml/init.rb b/railties/test/fixtures/about_yml_plugins/plugin_without_about_yml/init.rb
deleted file mode 100644
index 636bc1a8ab..0000000000
--- a/railties/test/fixtures/about_yml_plugins/plugin_without_about_yml/init.rb
+++ /dev/null
@@ -1 +0,0 @@
-# intentionally empty
diff --git a/railties/test/fixtures/lib/create_test_dummy_template.rb b/railties/test/fixtures/lib/create_test_dummy_template.rb
index e4378bbd1a..b9eb6a912d 100644
--- a/railties/test/fixtures/lib/create_test_dummy_template.rb
+++ b/railties/test/fixtures/lib/create_test_dummy_template.rb
@@ -1 +1,3 @@
+# frozen_string_literal: true
+
create_dummy_app("spec/dummy")
diff --git a/railties/test/fixtures/lib/generators/active_record/fixjour_generator.rb b/railties/test/fixtures/lib/generators/active_record/fixjour_generator.rb
index 1139350b94..f196971f20 100644
--- a/railties/test/fixtures/lib/generators/active_record/fixjour_generator.rb
+++ b/railties/test/fixtures/lib/generators/active_record/fixjour_generator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rails/generators/active_record"
module ActiveRecord
diff --git a/railties/test/fixtures/lib/generators/fixjour_generator.rb b/railties/test/fixtures/lib/generators/fixjour_generator.rb
index ef3e9edbed..22197835a8 100644
--- a/railties/test/fixtures/lib/generators/fixjour_generator.rb
+++ b/railties/test/fixtures/lib/generators/fixjour_generator.rb
@@ -1,2 +1,4 @@
+# frozen_string_literal: true
+
class FixjourGenerator < Rails::Generators::NamedBase
end
diff --git a/railties/test/fixtures/lib/generators/model_generator.rb b/railties/test/fixtures/lib/generators/model_generator.rb
index 0905fa9631..3009472c3d 100644
--- a/railties/test/fixtures/lib/generators/model_generator.rb
+++ b/railties/test/fixtures/lib/generators/model_generator.rb
@@ -1 +1,3 @@
+# frozen_string_literal: true
+
raise "I should never be loaded"
diff --git a/railties/test/fixtures/lib/generators/usage_template/usage_template_generator.rb b/railties/test/fixtures/lib/generators/usage_template/usage_template_generator.rb
index 701515440a..5a847a8bd2 100644
--- a/railties/test/fixtures/lib/generators/usage_template/usage_template_generator.rb
+++ b/railties/test/fixtures/lib/generators/usage_template/usage_template_generator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rails/generators"
class UsageTemplateGenerator < Rails::Generators::Base
diff --git a/railties/test/fixtures/lib/rails/generators/foobar/foobar_generator.rb b/railties/test/fixtures/lib/rails/generators/foobar/foobar_generator.rb
index d1de8c56fa..159843866c 100644
--- a/railties/test/fixtures/lib/rails/generators/foobar/foobar_generator.rb
+++ b/railties/test/fixtures/lib/rails/generators/foobar/foobar_generator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Foobar
class FoobarGenerator < Rails::Generators::Base
end
diff --git a/railties/test/fixtures/lib/template.rb b/railties/test/fixtures/lib/template.rb
index c14a1a8784..44083c25e8 100644
--- a/railties/test/fixtures/lib/template.rb
+++ b/railties/test/fixtures/lib/template.rb
@@ -1 +1,3 @@
+# frozen_string_literal: true
+
say "It works from file!"
diff --git a/railties/test/generators/actions_test.rb b/railties/test/generators/actions_test.rb
index 360e8e97d7..f421207025 100644
--- a/railties/test/generators/actions_test.rb
+++ b/railties/test/generators/actions_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "generators/generators_test_helper"
require "rails/generators/rails/app/app_generator"
require "env_helpers"
@@ -69,10 +71,17 @@ class ActionsTest < Rails::Generators::TestCase
def test_gem_with_version_should_include_version_in_gemfile
run_generator
-
- action :gem, "rspec", ">=2.0.0.a5"
-
- assert_file "Gemfile", /gem 'rspec', '>=2.0.0.a5'/
+ action :gem, "rspec", ">= 2.0.0.a5"
+ action :gem, "RedCloth", ">= 4.1.0", "< 4.2.0"
+ action :gem, "nokogiri", version: ">= 1.4.2"
+ action :gem, "faker", version: [">= 0.1.0", "< 0.3.0"]
+
+ assert_file "Gemfile" do |content|
+ assert_match(/gem 'rspec', '>= 2\.0\.0\.a5'/, content)
+ assert_match(/gem 'RedCloth', '>= 4\.1\.0', '< 4\.2\.0'/, content)
+ assert_match(/gem 'nokogiri', '>= 1\.4\.2'/, content)
+ assert_match(/gem 'faker', '>= 0\.1\.0', '< 0\.3\.0'/, content)
+ end
end
def test_gem_should_insert_on_separate_lines
@@ -139,14 +148,14 @@ class ActionsTest < Rails::Generators::TestCase
run_generator
autoload_paths = 'config.autoload_paths += %w["#{Rails.root}/app/extras"]'
action :environment, autoload_paths
- assert_file "config/application.rb", / class Application < Rails::Application\n #{Regexp.escape(autoload_paths)}/
+ assert_file "config/application.rb", / class Application < Rails::Application\n #{Regexp.escape(autoload_paths)}\n/
end
def test_environment_should_include_data_in_environment_initializer_block_with_env_option
run_generator
autoload_paths = 'config.autoload_paths += %w["#{Rails.root}/app/extras"]'
action :environment, autoload_paths, env: "development"
- assert_file "config/environments/development.rb", /Rails\.application\.configure do\n #{Regexp.escape(autoload_paths)}/
+ assert_file "config/environments/development.rb", /Rails\.application\.configure do\n #{Regexp.escape(autoload_paths)}\n/
end
def test_environment_with_block_should_include_block_contents_in_environment_initializer_block
@@ -163,6 +172,26 @@ class ActionsTest < Rails::Generators::TestCase
end
end
+ def test_environment_with_block_should_include_block_contents_with_multiline_data_in_environment_initializer_block
+ run_generator
+ data = <<-RUBY
+ config.encoding = "utf-8"
+ config.time_zone = "UTC"
+ RUBY
+ action(:environment) { data }
+ assert_file "config/application.rb", / class Application < Rails::Application\n#{Regexp.escape(data.strip_heredoc.indent(4))}/
+ end
+
+ def test_environment_should_include_block_contents_with_multiline_data_in_environment_initializer_block_with_env_option
+ run_generator
+ data = <<-RUBY
+ config.encoding = "utf-8"
+ config.time_zone = "UTC"
+ RUBY
+ action(:environment, nil, env: "development") { data }
+ assert_file "config/environments/development.rb", /Rails\.application\.configure do\n#{Regexp.escape(data.strip_heredoc.indent(2))}/
+ end
+
def test_git_with_symbol_should_run_command_using_git_scm
assert_called_with(generator, :run, ["git init"]) do
action :git, :init
@@ -177,22 +206,62 @@ class ActionsTest < Rails::Generators::TestCase
def test_vendor_should_write_data_to_file_in_vendor
action :vendor, "vendor_file.rb", "# vendor data"
- assert_file "vendor/vendor_file.rb", "# vendor data"
+ assert_file "vendor/vendor_file.rb", "# vendor data\n"
+ end
+
+ def test_vendor_should_write_data_to_file_with_block_in_vendor
+ code = <<-RUBY
+ puts "one"
+ puts "two"
+ puts "three"
+ RUBY
+ action(:vendor, "vendor_file.rb") { code }
+ assert_file "vendor/vendor_file.rb", code.strip_heredoc
end
def test_lib_should_write_data_to_file_in_lib
action :lib, "my_library.rb", "class MyLibrary"
- assert_file "lib/my_library.rb", "class MyLibrary"
+ assert_file "lib/my_library.rb", "class MyLibrary\n"
+ end
+
+ def test_lib_should_write_data_to_file_with_block_in_lib
+ code = <<-RUBY
+ class MyLib
+ MY_CONSTANT = 123
+ end
+ RUBY
+ action(:lib, "my_library.rb") { code }
+ assert_file "lib/my_library.rb", code.strip_heredoc
end
def test_rakefile_should_write_date_to_file_in_lib_tasks
action :rakefile, "myapp.rake", "task run: [:environment]"
- assert_file "lib/tasks/myapp.rake", "task run: [:environment]"
+ assert_file "lib/tasks/myapp.rake", "task run: [:environment]\n"
+ end
+
+ def test_rakefile_should_write_date_to_file_with_block_in_lib_tasks
+ code = <<-RUBY
+ task rock: :environment do
+ puts "Rockin'"
+ end
+ RUBY
+ action(:rakefile, "myapp.rake") { code }
+ assert_file "lib/tasks/myapp.rake", code.strip_heredoc
end
def test_initializer_should_write_date_to_file_in_config_initializers
action :initializer, "constants.rb", "MY_CONSTANT = 42"
- assert_file "config/initializers/constants.rb", "MY_CONSTANT = 42"
+ assert_file "config/initializers/constants.rb", "MY_CONSTANT = 42\n"
+ end
+
+ def test_initializer_should_write_date_to_file_with_block_in_config_initializers
+ code = <<-RUBY
+ MyLib.configure do |config|
+ config.value = 123
+ end
+ RUBY
+ action(:initializer, "constants.rb") { code }
+ assert_file "config/initializers/constants.rb", code.strip_heredoc
end
def test_generate_should_run_script_generate_with_argument_and_options
@@ -239,6 +308,14 @@ class ActionsTest < Rails::Generators::TestCase
end
end
+ test "rake command with capture option should run rake command with capture" do
+ assert_called_with(generator, :run, ["rake log:clear RAILS_ENV=development", verbose: false, capture: true]) do
+ with_rails_env nil do
+ action :rake, "log:clear", capture: true
+ end
+ end
+ end
+
test "rails command should run rails_command with default env" do
assert_called_with(generator, :run, ["rails log:clear RAILS_ENV=development", verbose: false]) do
with_rails_env nil do
@@ -277,10 +354,21 @@ class ActionsTest < Rails::Generators::TestCase
end
end
+ test "rails command with capture option should run rails_command with capture" do
+ assert_called_with(generator, :run, ["rails log:clear RAILS_ENV=development", verbose: false, capture: true]) do
+ with_rails_env nil do
+ action :rails_command, "log:clear", capture: true
+ end
+ end
+ end
+
def test_capify_should_run_the_capify_command
- assert_called_with(generator, :run, ["capify .", verbose: false]) do
- action :capify!
+ content = capture(:stderr) do
+ assert_called_with(generator, :run, ["capify .", verbose: false]) do
+ action :capify!
+ end
end
+ assert_match(/DEPRECATION WARNING: `capify!` is deprecated/, content)
end
def test_route_should_add_data_to_the_routes_block_in_config_routes
diff --git a/railties/test/generators/api_app_generator_test.rb b/railties/test/generators/api_app_generator_test.rb
index a19e0f0dd8..7791d472d8 100644
--- a/railties/test/generators/api_app_generator_test.rb
+++ b/railties/test/generators/api_app_generator_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "generators/generators_test_helper"
require "rails/generators/rails/app/app_generator"
@@ -33,26 +35,26 @@ class ApiAppGeneratorTest < Rails::Generators::TestCase
def test_api_modified_files
run_generator
+ assert_file ".gitignore" do |content|
+ assert_no_match(/\/public\/assets/, content)
+ 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)
+ assert_no_match(/gem 'selenium-webdriver'/, content)
assert_match(/# gem 'jbuilder'/, content)
+ assert_match(/# gem 'rack-cors'/, content)
end
- assert_file "config/application.rb" do |content|
- assert_match(/config.api_only = true/, content)
- end
-
- assert_file "config/initializers/cors.rb"
-
- assert_file "config/initializers/wrap_parameters.rb"
-
+ assert_file "config/application.rb", /config\.api_only = true/
assert_file "app/controllers/application_controller.rb", /ActionController::API/
end
def test_generator_if_skip_action_cable_is_given
- run_generator [destination_root, "--skip-action-cable"]
+ run_generator [destination_root, "--api", "--skip-action-cable"]
assert_file "config/application.rb", /#\s+require\s+["']action_cable\/engine["']/
assert_no_file "config/cable.yml"
assert_no_file "app/channels"
@@ -65,7 +67,7 @@ class ApiAppGeneratorTest < Rails::Generators::TestCase
run_generator
generator = Rails::Generators::AppGenerator.new ["rails"],
- { api: true, update: true }, destination_root: destination_root, shell: @shell
+ { api: true, update: true }, { destination_root: destination_root, shell: @shell }
quietly { generator.send(:update_config_files) }
assert_no_file "config/initializers/cookies_serializer.rb"
@@ -76,7 +78,7 @@ class ApiAppGeneratorTest < Rails::Generators::TestCase
run_generator
generator = Rails::Generators::AppGenerator.new ["rails"],
- { api: true, update: true }, destination_root: destination_root, shell: @shell
+ { api: true, update: true }, { destination_root: destination_root, shell: @shell }
quietly { generator.send(:update_bin_files) }
assert_no_file "bin/yarn"
@@ -85,20 +87,49 @@ class ApiAppGeneratorTest < Rails::Generators::TestCase
private
def default_files
- files = %W(
- .gitignore
+ %w(.gitignore
+ .ruby-version
+ README.md
Gemfile
Rakefile
config.ru
+ app/channels
app/controllers
app/mailers
app/models
+ app/views/layouts
app/views/layouts/mailer.html.erb
app/views/layouts/mailer.text.erb
+ bin/bundle
+ bin/rails
+ bin/rake
+ bin/setup
+ bin/update
+ config/application.rb
+ config/boot.rb
+ config/cable.yml
+ config/environment.rb
config/environments
+ config/environments/development.rb
+ config/environments/production.rb
+ config/environments/test.rb
config/initializers
+ config/initializers/application_controller_renderer.rb
+ config/initializers/backtrace_silencers.rb
+ config/initializers/cors.rb
+ config/initializers/filter_parameter_logging.rb
+ config/initializers/inflections.rb
+ config/initializers/mime_types.rb
+ config/initializers/wrap_parameters.rb
config/locales
+ config/locales/en.yml
+ config/puma.rb
+ config/routes.rb
+ config/credentials.yml.enc
+ config/spring.rb
+ config/storage.yml
db
+ db/seeds.rb
lib
lib/tasks
log
@@ -109,8 +140,6 @@ class ApiAppGeneratorTest < Rails::Generators::TestCase
tmp
vendor
)
- files.concat %w(bin/bundle bin/rails bin/rake)
- files
end
def skipped_files
@@ -128,7 +157,7 @@ class ApiAppGeneratorTest < Rails::Generators::TestCase
public/500.html
public/apple-touch-icon-precomposed.png
public/apple-touch-icon.png
- public/favicon.icon
+ public/favicon.ico
package.json
)
end
diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb
index 8a8c9a35ce..fddfab172e 100644
--- a/railties/test/generators/app_generator_test.rb
+++ b/railties/test/generators/app_generator_test.rb
@@ -1,39 +1,82 @@
+# frozen_string_literal: true
+
require "generators/generators_test_helper"
require "rails/generators/rails/app/app_generator"
require "generators/shared_generator_tests"
DEFAULT_APP_FILES = %w(
.gitignore
+ .ruby-version
README.md
Gemfile
Rakefile
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/assets/stylesheets
- app/assets/images
+ app/assets/stylesheets/application.css
+ app/channels/application_cable/channel.rb
+ app/channels/application_cable/connection.rb
app/controllers
+ app/controllers/application_controller.rb
app/controllers/concerns
app/helpers
+ app/helpers/application_helper.rb
app/mailers
+ app/mailers/application_mailer.rb
app/models
+ app/models/application_record.rb
app/models/concerns
app/jobs
+ app/jobs/application_job.rb
app/views/layouts
+ app/views/layouts/application.html.erb
+ app/views/layouts/mailer.html.erb
+ app/views/layouts/mailer.text.erb
bin/bundle
bin/rails
bin/rake
bin/setup
+ bin/update
+ bin/yarn
+ config/application.rb
+ config/boot.rb
+ config/cable.yml
+ config/environment.rb
config/environments
+ config/environments/development.rb
+ config/environments/production.rb
+ config/environments/test.rb
config/initializers
+ config/initializers/application_controller_renderer.rb
+ config/initializers/assets.rb
+ config/initializers/backtrace_silencers.rb
+ config/initializers/cookies_serializer.rb
+ config/initializers/filter_parameter_logging.rb
+ config/initializers/inflections.rb
+ config/initializers/mime_types.rb
+ config/initializers/wrap_parameters.rb
config/locales
- config/cable.yml
+ config/locales/en.yml
config/puma.rb
+ config/routes.rb
+ config/credentials.yml.enc
config/spring.rb
+ config/storage.yml
db
+ db/seeds.rb
lib
lib/tasks
lib/assets
log
+ package.json
+ public
+ storage
+ test/application_system_test_case.rb
test/test_helper.rb
test/fixtures
test/fixtures/files
@@ -47,6 +90,7 @@ DEFAULT_APP_FILES = %w(
tmp
tmp/cache
tmp/cache/assets
+ tmp/storage
)
class AppGeneratorTest < Rails::Generators::TestCase
@@ -206,7 +250,7 @@ class AppGeneratorTest < Rails::Generators::TestCase
assert_no_file "#{app_root}/config/initializers/new_framework_defaults_5_2.rb"
stub_rails_application(app_root) do
- generator = Rails::Generators::AppGenerator.new ["rails"], { update: true }, destination_root: app_root, shell: @shell
+ generator = Rails::Generators::AppGenerator.new ["rails"], { update: true }, { destination_root: app_root, shell: @shell }
generator.send(:app_const)
quietly { generator.send(:update_config_files) }
@@ -240,6 +284,94 @@ class AppGeneratorTest < Rails::Generators::TestCase
end
end
+ def test_app_update_does_not_generate_action_cable_contents_when_skip_action_cable_is_given
+ app_root = File.join(destination_root, "myapp")
+ run_generator [app_root, "--skip-action-cable"]
+
+ FileUtils.cd(app_root) do
+ quietly { system("bin/rails app:update") }
+ end
+
+ assert_no_file "#{app_root}/config/cable.yml"
+ assert_file "#{app_root}/config/environments/production.rb" do |content|
+ assert_no_match(/config\.action_cable/, content)
+ end
+ end
+
+ def test_active_storage_mini_magick_gem
+ run_generator
+ assert_file "Gemfile", /^# gem 'mini_magick'/
+ end
+
+ def test_active_storage_install
+ command_check = -> command, _ do
+ @binstub_called ||= 0
+ case command
+ when "active_storage:install"
+ @binstub_called += 1
+ assert_equal 1, @binstub_called, "active_storage:install expected to be called once, but was called #{@install_called} times."
+ end
+ end
+
+ generator.stub :rails_command, command_check do
+ quietly { generator.invoke_all }
+ end
+ end
+
+ def test_app_update_does_not_generate_active_storage_contents_when_skip_active_storage_is_given
+ app_root = File.join(destination_root, "myapp")
+ run_generator [app_root, "--skip-active-storage"]
+
+ FileUtils.cd(app_root) do
+ quietly { system("bin/rails app:update") }
+ end
+
+ assert_file "#{app_root}/config/environments/development.rb" do |content|
+ assert_no_match(/config\.active_storage/, content)
+ end
+
+ assert_file "#{app_root}/config/environments/production.rb" do |content|
+ assert_no_match(/config\.active_storage/, content)
+ end
+
+ assert_file "#{app_root}/config/environments/test.rb" do |content|
+ assert_no_match(/config\.active_storage/, content)
+ end
+
+ assert_no_file "#{app_root}/config/storage.yml"
+
+ assert_file "#{app_root}/Gemfile" do |content|
+ assert_no_match(/gem 'mini_magick'/, content)
+ end
+ end
+
+ def test_app_update_does_not_generate_active_storage_contents_when_skip_active_record_is_given
+ app_root = File.join(destination_root, "myapp")
+ run_generator [app_root, "--skip-active-record"]
+
+ FileUtils.cd(app_root) do
+ quietly { system("bin/rails app:update") }
+ end
+
+ assert_file "#{app_root}/config/environments/development.rb" do |content|
+ assert_no_match(/config\.active_storage/, content)
+ end
+
+ assert_file "#{app_root}/config/environments/production.rb" do |content|
+ assert_no_match(/config\.active_storage/, content)
+ end
+
+ assert_file "#{app_root}/config/environments/test.rb" do |content|
+ assert_no_match(/config\.active_storage/, content)
+ end
+
+ assert_no_file "#{app_root}/config/storage.yml"
+
+ assert_file "#{app_root}/Gemfile" do |content|
+ assert_no_match(/gem 'mini_magick'/, content)
+ end
+ end
+
def test_application_names_are_not_singularized
run_generator [File.join(destination_root, "hats")]
assert_file "hats/config/environment.rb", /Rails\.application\.initialize!/
@@ -323,21 +455,6 @@ class AppGeneratorTest < Rails::Generators::TestCase
end
end
- def test_generator_without_skips
- run_generator
- assert_file "config/application.rb", /\s+require\s+["']rails\/all["']/
- assert_file "config/environments/development.rb" do |content|
- assert_match(/config\.action_mailer\.raise_delivery_errors = false/, content)
- end
- assert_file "config/environments/test.rb" do |content|
- assert_match(/config\.action_mailer\.delivery_method = :test/, content)
- end
- assert_file "config/environments/production.rb" do |content|
- assert_match(/# config\.action_mailer\.raise_delivery_errors = false/, content)
- assert_match(/^ config\.read_encrypted_secrets = true/, content)
- end
- end
-
def test_generator_defaults_to_puma_version
run_generator [destination_root]
assert_gem "puma", "'~> 3.7'"
@@ -351,39 +468,6 @@ class AppGeneratorTest < Rails::Generators::TestCase
end
end
- def test_generator_if_skip_active_record_is_given
- run_generator [destination_root, "--skip-active-record"]
- assert_no_directory "db/"
- assert_no_file "config/database.yml"
- assert_no_file "app/models/application_record.rb"
- assert_file "config/application.rb", /#\s+require\s+["']active_record\/railtie["']/
- assert_file "test/test_helper.rb" do |helper_content|
- assert_no_match(/fixtures :all/, helper_content)
- end
- assert_file "bin/setup" do |setup_content|
- assert_no_match(/db:setup/, setup_content)
- end
- assert_file "bin/update" do |update_content|
- assert_no_match(/db:migrate/, update_content)
- end
- end
-
- def test_generator_if_skip_action_mailer_is_given
- run_generator [destination_root, "--skip-action-mailer"]
- assert_file "config/application.rb", /#\s+require\s+["']action_mailer\/railtie["']/
- assert_file "config/environments/development.rb" do |content|
- assert_no_match(/config\.action_mailer/, content)
- end
- assert_file "config/environments/test.rb" do |content|
- assert_no_match(/config\.action_mailer/, content)
- end
- assert_file "config/environments/production.rb" do |content|
- assert_no_match(/config\.action_mailer/, content)
- end
- assert_no_directory "app/mailers"
- assert_no_directory "test/mailers"
- end
-
def test_generator_has_assets_gems
run_generator
@@ -391,38 +475,6 @@ class AppGeneratorTest < Rails::Generators::TestCase
assert_gem "uglifier"
end
- def test_generator_if_skip_sprockets_is_given
- run_generator [destination_root, "--skip-sprockets"]
- assert_no_file "config/initializers/assets.rb"
- assert_file "config/application.rb" do |content|
- assert_match(/#\s+require\s+["']sprockets\/railtie["']/, content)
- end
- 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 "config/environments/development.rb" do |content|
- assert_no_match(/config\.assets\.debug = true/, content)
- end
- assert_file "config/environments/production.rb" do |content|
- assert_no_match(/config\.assets\.digest = true/, content)
- assert_no_match(/config\.assets\.js_compressor = :uglifier/, content)
- assert_no_match(/config\.assets\.css_compressor = :sass/, content)
- end
- end
-
- def test_generator_if_skip_action_cable_is_given
- run_generator [destination_root, "--skip-action-cable"]
- assert_file "config/application.rb", /#\s+require\s+["']action_cable\/engine["']/
- assert_no_file "config/cable.yml"
- assert_no_file "app/assets/javascripts/cable.js"
- assert_no_file "app/channels"
- assert_file "Gemfile" do |content|
- assert_no_match(/redis/, content)
- end
- end
-
def test_action_cable_redis_gems
run_generator
assert_file "Gemfile", /^# gem 'redis'/
@@ -430,22 +482,33 @@ class AppGeneratorTest < Rails::Generators::TestCase
def test_generator_if_skip_test_is_given
run_generator [destination_root, "--skip-test"]
+
+ assert_file "config/application.rb", /#\s+require\s+["']rails\/test_unit\/railtie["']/
+
assert_file "Gemfile" do |content|
assert_no_match(/capybara/, content)
assert_no_match(/selenium-webdriver/, content)
+ assert_no_match(/chromedriver-helper/, content)
end
+
+ assert_no_directory("test")
end
def test_generator_if_skip_system_test_is_given
- run_generator [destination_root, "--skip_system_test"]
+ run_generator [destination_root, "--skip-system-test"]
assert_file "Gemfile" do |content|
assert_no_match(/capybara/, content)
assert_no_match(/selenium-webdriver/, content)
+ assert_no_match(/chromedriver-helper/, content)
end
+
+ assert_directory("test")
+
+ assert_no_directory("test/system")
end
def test_does_not_generate_system_test_files_if_skip_system_test_is_given
- run_generator [destination_root, "--skip_system_test"]
+ run_generator [destination_root, "--skip-system-test"]
Dir.chdir(destination_root) do
quietly { `./bin/rails g scaffold User` }
@@ -455,18 +518,12 @@ class AppGeneratorTest < Rails::Generators::TestCase
end
end
- def test_generator_if_api_is_given
- run_generator [destination_root, "--api"]
- assert_file "Gemfile" do |content|
- assert_no_match(/capybara/, content)
- assert_no_match(/selenium-webdriver/, content)
- 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
@@ -508,27 +565,6 @@ class AppGeneratorTest < Rails::Generators::TestCase
end
end
- def test_generator_for_yarn
- run_generator([destination_root])
- assert_file "package.json", /dependencies/
- assert_file "config/initializers/assets.rb", /node_modules/
- end
-
- def test_generator_for_yarn_skipped
- run_generator([destination_root, "--skip-yarn"])
- assert_no_file "package.json"
- assert_no_file "bin/yarn"
-
- assert_file "config/initializers/assets.rb" do |content|
- assert_no_match(/node_modules/, content)
- end
-
- assert_file ".gitignore" do |content|
- assert_no_match(/node_modules/, content)
- assert_no_match(/yarn-error\.log/, content)
- end
- end
-
def test_inclusion_of_jbuilder
run_generator
assert_gem "jbuilder"
@@ -596,24 +632,17 @@ class AppGeneratorTest < Rails::Generators::TestCase
assert_file "lib/test_file.rb", "heres test data"
end
- def test_tests_are_removed_from_frameworks_if_skip_test_is_given
- run_generator [destination_root, "--skip-test"]
- assert_file "config/application.rb", /#\s+require\s+["']rails\/test_unit\/railtie["']/
- end
-
- def test_no_active_record_or_tests_if_skips_given
- run_generator [destination_root, "--skip-test", "--skip-active-record"]
- assert_file "config/application.rb", /#\s+require\s+["']rails\/test_unit\/railtie["']/
- assert_file "config/application.rb", /#\s+require\s+["']active_record\/railtie["']/
- assert_file "config/application.rb", /\s+require\s+["']active_job\/railtie["']/
- end
-
def test_pretend_option
output = run_generator [File.join(destination_root, "myapp"), "--pretend"]
assert_no_match(/run bundle install/, output)
assert_no_match(/run git init/, output)
end
+ def test_quiet_option
+ output = run_generator [File.join(destination_root, "myapp"), "--quiet"]
+ assert_empty output
+ end
+
def test_application_name_with_spaces
path = File.join(destination_root, "foo bar")
@@ -727,27 +756,14 @@ class AppGeneratorTest < Rails::Generators::TestCase
end
end
- def test_gitignore_when_sqlite3
+ def test_inclusion_of_ruby_version
run_generator
- assert_file ".gitignore" do |content|
- assert_match(/sqlite3/, content)
+ assert_file "Gemfile" do |content|
+ assert_match(/ruby '#{RUBY_VERSION}'/, content)
end
- end
-
- def test_gitignore_when_no_active_record
- run_generator [destination_root, "--skip-active-record"]
-
- assert_file ".gitignore" do |content|
- assert_no_match(/sqlite/i, content)
- end
- end
-
- def test_gitignore_when_non_sqlite3_db
- run_generator([destination_root, "-d", "mysql"])
-
- assert_file ".gitignore" do |content|
- assert_no_match(/sqlite/i, content)
+ assert_file ".ruby-version" do |content|
+ assert_match(/#{RUBY_VERSION}/, content)
end
end
@@ -794,7 +810,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' } }
+ template = %{ after_bundle { run 'echo ran after_bundle' } }.dup
template.instance_eval "def read; self; end" # Make the string respond to read
check_open = -> *args do
@@ -802,9 +818,9 @@ class AppGeneratorTest < Rails::Generators::TestCase
template
end
- sequence = ["git init", "install", "exec spring binstub --all", "echo ran after_bundle"]
+ sequence = ["git init", "install", "exec spring binstub --all", "active_storage:install", "echo ran after_bundle"]
@sequence_step ||= 0
- ensure_bundler_first = -> command do
+ ensure_bundler_first = -> command, options = nil do
assert_equal sequence[@sequence_step], command, "commands should be called in sequence #{sequence}"
@sequence_step += 1
end
@@ -812,31 +828,29 @@ class AppGeneratorTest < Rails::Generators::TestCase
generator([destination_root], template: path).stub(:open, check_open, template) do
generator.stub(:bundle_command, ensure_bundler_first) do
generator.stub(:run, ensure_bundler_first) do
- quietly { generator.invoke_all }
+ generator.stub(:rails_command, ensure_bundler_first) do
+ quietly { generator.invoke_all }
+ end
end
end
end
- assert_equal 4, @sequence_step
+ assert_equal 5, @sequence_step
end
- def test_system_tests_directory_generated
+ def test_gitignore
run_generator
- assert_file("test/system/.keep")
- assert_directory("test/system")
- end
-
- def test_system_tests_are_not_generated_on_system_test_skip
- run_generator [destination_root, "--skip-system-test"]
-
- assert_no_directory("test/system")
+ assert_file ".gitignore" do |content|
+ assert_match(/config\/master\.key/, content)
+ end
end
- def test_system_tests_are_not_generated_on_test_skip
- run_generator [destination_root, "--skip-test"]
+ def test_system_tests_directory_generated
+ run_generator
- assert_no_directory("test/system")
+ assert_file("test/system/.keep")
+ assert_directory("test/system")
end
private
diff --git a/railties/test/generators/application_record_generator_test.rb b/railties/test/generators/application_record_generator_test.rb
new file mode 100644
index 0000000000..2c0aa7211b
--- /dev/null
+++ b/railties/test/generators/application_record_generator_test.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+require "generators/generators_test_helper"
+require "rails/generators/rails/application_record/application_record_generator"
+
+class ApplicationRecordGeneratorTest < Rails::Generators::TestCase
+ include GeneratorsTestHelper
+
+ def test_application_record_skeleton_is_created
+ run_generator
+ assert_file "app/models/application_record.rb" do |record|
+ assert_match(/class ApplicationRecord < ActiveRecord::Base/, record)
+ assert_match(/self\.abstract_class = true/, record)
+ end
+ end
+end
diff --git a/railties/test/generators/argv_scrubber_test.rb b/railties/test/generators/argv_scrubber_test.rb
index 7f4295a20f..9ef61dc978 100644
--- a/railties/test/generators/argv_scrubber_test.rb
+++ b/railties/test/generators/argv_scrubber_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "active_support/test_case"
require "active_support/testing/autorun"
require "rails/generators/rails/app/app_generator"
@@ -80,9 +82,8 @@ module Rails
file.puts "--hello --world"
file.flush
- message = nil
scrubber = Class.new(ARGVScrubber) {
- define_method(:puts) { |msg| message = msg }
+ define_method(:puts) { |msg| }
}.new ["new", "--rc=#{file.path}"]
args = scrubber.prepare!
assert_equal ["--hello", "--world"], args
diff --git a/railties/test/generators/assets_generator_test.rb b/railties/test/generators/assets_generator_test.rb
index 1c02c67e42..3cec41dbf8 100644
--- a/railties/test/generators/assets_generator_test.rb
+++ b/railties/test/generators/assets_generator_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "generators/generators_test_helper"
require "rails/generators/rails/assets/assets_generator"
diff --git a/railties/test/generators/channel_generator_test.rb b/railties/test/generators/channel_generator_test.rb
index af68a9c49f..e238197eba 100644
--- a/railties/test/generators/channel_generator_test.rb
+++ b/railties/test/generators/channel_generator_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "generators/generators_test_helper"
require "rails/generators/channel/channel_generator"
diff --git a/railties/test/generators/controller_generator_test.rb b/railties/test/generators/controller_generator_test.rb
index af86a0136f..a3218951a6 100644
--- a/railties/test/generators/controller_generator_test.rb
+++ b/railties/test/generators/controller_generator_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "generators/generators_test_helper"
require "rails/generators/rails/controller/controller_generator"
@@ -100,4 +102,11 @@ class ControllerGeneratorTest < Rails::Generators::TestCase
assert_match(/^ namespace :admin do\n get 'dashboard\/index'\n end$/, route)
end
end
+
+ def test_namespaced_routes_with_multiple_actions_are_created_in_routes
+ run_generator ["admin/dashboard", "index", "show"]
+ assert_file "config/routes.rb" do |route|
+ assert_match(/^ namespace :admin do\n get 'dashboard\/index'\n get 'dashboard\/show'\n end$/, route)
+ end
+ end
end
diff --git a/railties/test/generators/create_migration_test.rb b/railties/test/generators/create_migration_test.rb
index c7b0237f02..3cb7fd6baa 100644
--- a/railties/test/generators/create_migration_test.rb
+++ b/railties/test/generators/create_migration_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "generators/generators_test_helper"
require "rails/generators/rails/migration/migration_generator"
@@ -51,7 +53,7 @@ class CreateMigrationTest < Rails::Generators::TestCase
end
def test_invoke_pretended
- create_migration(default_destination_path, {}, pretend: true)
+ create_migration(default_destination_path, {}, { pretend: true })
assert_no_file @migration.destination
end
@@ -92,7 +94,7 @@ class CreateMigrationTest < Rails::Generators::TestCase
def test_invoke_forced_pretended_when_exists_not_identical
migration_exists!
- create_migration(default_destination_path, { force: true }, pretend: true) do
+ create_migration(default_destination_path, { force: true }, { pretend: true }) do
"different content"
end
@@ -104,7 +106,7 @@ class CreateMigrationTest < Rails::Generators::TestCase
def test_invoke_skipped_when_exists_not_identical
migration_exists!
- create_migration(default_destination_path, {}, skip: true) { "different content" }
+ create_migration(default_destination_path, {}, { skip: true }) { "different content" }
assert_match(/skip db\/migrate\/2_create_articles\.rb\n/, invoke!)
assert_no_file @migration.destination
@@ -120,7 +122,7 @@ class CreateMigrationTest < Rails::Generators::TestCase
def test_revoke_pretended
migration_exists!
- create_migration(default_destination_path, {}, pretend: true)
+ create_migration(default_destination_path, {}, { pretend: true })
assert_match(/remove db\/migrate\/1_create_articles\.rb\n/, revoke!)
assert_file @existing_migration.destination
diff --git a/railties/test/generators/encrypted_secrets_generator_test.rb b/railties/test/generators/encrypted_secrets_generator_test.rb
deleted file mode 100644
index 21fdcab19f..0000000000
--- a/railties/test/generators/encrypted_secrets_generator_test.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-require "generators/generators_test_helper"
-require "rails/generators/rails/encrypted_secrets/encrypted_secrets_generator"
-
-class EncryptedSecretsGeneratorTest < Rails::Generators::TestCase
- include GeneratorsTestHelper
-
- def setup
- super
- cd destination_root
- end
-
- def test_generates_key_file_and_encrypted_secrets_file
- run_generator
-
- assert_file "config/secrets.yml.key", /\w+/
-
- assert File.exist?("config/secrets.yml.enc")
- assert_no_match(/production:\n# external_api_key: \w+/, IO.binread("config/secrets.yml.enc"))
- assert_match(/production:\n# external_api_key: \w+/, Rails::Secrets.read)
- end
-
- def test_appends_to_gitignore
- FileUtils.touch(".gitignore")
-
- run_generator
-
- assert_file ".gitignore", /config\/secrets.yml.key/, /(?!config\/secrets.yml.enc)/
- end
-
- def test_warns_when_ignore_is_missing
- assert_match(/Add this to your ignore file/i, run_generator)
- end
-
- def test_doesnt_generate_a_new_key_file_if_already_opted_in_to_encrypted_secrets
- FileUtils.mkdir("config")
- File.open("config/secrets.yml.enc", "w") { |f| f.puts "already secrety" }
-
- run_generator
-
- assert_no_file "config/secrets.yml.key"
- end
-end
diff --git a/railties/test/generators/generated_attribute_test.rb b/railties/test/generators/generated_attribute_test.rb
index 97847c8624..c6f7bdeda1 100644
--- a/railties/test/generators/generated_attribute_test.rb
+++ b/railties/test/generators/generated_attribute_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "generators/generators_test_helper"
require "rails/generators/generated_attribute"
diff --git a/railties/test/generators/generator_generator_test.rb b/railties/test/generators/generator_generator_test.rb
index 5ff8bb0357..eaa964cabc 100644
--- a/railties/test/generators/generator_generator_test.rb
+++ b/railties/test/generators/generator_generator_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "generators/generators_test_helper"
require "rails/generators/rails/generator/generator_generator"
diff --git a/railties/test/generators/generator_test.rb b/railties/test/generators/generator_test.rb
index 4444b3a56e..5f7daf5ac3 100644
--- a/railties/test/generators/generator_test.rb
+++ b/railties/test/generators/generator_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "active_support/test_case"
require "active_support/testing/autorun"
require "rails/generators/app_base"
diff --git a/railties/test/generators/generators_test_helper.rb b/railties/test/generators/generators_test_helper.rb
index 5fb331e197..ad2a55f496 100644
--- a/railties/test/generators/generators_test_helper.rb
+++ b/railties/test/generators/generators_test_helper.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "abstract_unit"
require "active_support/core_ext/module/remove_method"
require "active_support/testing/stream"
@@ -41,9 +43,9 @@ module GeneratorsTestHelper
end
def copy_routes
- routes = File.expand_path("../../lib/rails/generators/rails/app/templates/config/routes.rb", __dir__)
+ routes = File.expand_path("../../lib/rails/generators/rails/app/templates/config/routes.rb.tt", __dir__)
destination = File.join(destination_root, "config")
FileUtils.mkdir_p(destination)
- FileUtils.cp routes, destination
+ FileUtils.cp routes, File.join(destination, "routes.rb")
end
end
diff --git a/railties/test/generators/helper_generator_test.rb b/railties/test/generators/helper_generator_test.rb
index d9e6e0a85a..4cdb6adf82 100644
--- a/railties/test/generators/helper_generator_test.rb
+++ b/railties/test/generators/helper_generator_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "generators/generators_test_helper"
require "rails/generators/rails/helper/helper_generator"
diff --git a/railties/test/generators/integration_test_generator_test.rb b/railties/test/generators/integration_test_generator_test.rb
index 9358b63bd4..82791f1a27 100644
--- a/railties/test/generators/integration_test_generator_test.rb
+++ b/railties/test/generators/integration_test_generator_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "generators/generators_test_helper"
require "rails/generators/rails/integration_test/integration_test_generator"
diff --git a/railties/test/generators/job_generator_test.rb b/railties/test/generators/job_generator_test.rb
index 68d158eb39..13276fac65 100644
--- a/railties/test/generators/job_generator_test.rb
+++ b/railties/test/generators/job_generator_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "generators/generators_test_helper"
require "rails/generators/job/job_generator"
diff --git a/railties/test/generators/mailer_generator_test.rb b/railties/test/generators/mailer_generator_test.rb
index 2ff03ea65e..ddac6e1a1e 100644
--- a/railties/test/generators/mailer_generator_test.rb
+++ b/railties/test/generators/mailer_generator_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "generators/generators_test_helper"
require "rails/generators/mailer/mailer_generator"
diff --git a/railties/test/generators/migration_generator_test.rb b/railties/test/generators/migration_generator_test.rb
index 6fe6e4ca07..88a939a55a 100644
--- a/railties/test/generators/migration_generator_test.rb
+++ b/railties/test/generators/migration_generator_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "generators/generators_test_helper"
require "rails/generators/rails/migration/migration_generator"
@@ -48,6 +50,17 @@ class MigrationGeneratorTest < Rails::Generators::TestCase
end
end
+ def test_add_migration_with_table_having_from_in_title
+ migration = "add_email_address_to_blacklisted_from_campaign"
+ run_generator [migration, "email_address:string"]
+
+ assert_migration "db/migrate/#{migration}.rb" do |content|
+ assert_method :change, content do |change|
+ assert_match(/add_column :blacklisted_from_campaigns, :email_address, :string/, change)
+ end
+ end
+ end
+
def test_remove_migration_with_indexed_attribute
migration = "remove_title_body_from_posts"
run_generator [migration, "title:string:index", "body:text"]
@@ -73,6 +86,17 @@ class MigrationGeneratorTest < Rails::Generators::TestCase
end
end
+ def test_remove_migration_with_table_having_to_in_title
+ migration = "remove_email_address_from_sent_to_user"
+ run_generator [migration, "email_address:string"]
+
+ assert_migration "db/migrate/#{migration}.rb" do |content|
+ assert_method :change, content do |change|
+ assert_match(/remove_column :sent_to_users, :email_address, :string/, change)
+ end
+ end
+ end
+
def test_remove_migration_with_references_options
migration = "remove_references_from_books"
run_generator [migration, "author:belongs_to", "distributor:references{polymorphic}"]
diff --git a/railties/test/generators/model_generator_test.rb b/railties/test/generators/model_generator_test.rb
index f41969fc46..516aa0704f 100644
--- a/railties/test/generators/model_generator_test.rb
+++ b/railties/test/generators/model_generator_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "generators/generators_test_helper"
require "rails/generators/rails/model/model_generator"
require "active_support/core_ext/string/strip"
@@ -6,14 +8,6 @@ class ModelGeneratorTest < Rails::Generators::TestCase
include GeneratorsTestHelper
arguments %w(Account name:string age:integer)
- def test_application_record_skeleton_is_created
- run_generator
- assert_file "app/models/application_record.rb" do |record|
- assert_match(/class ApplicationRecord < ActiveRecord::Base/, record)
- assert_match(/self\.abstract_class = true/, record)
- end
- end
-
def test_help_shows_invoked_generators_options
content = run_generator ["--help"]
assert_match(/ActiveRecord options:/, content)
@@ -43,17 +37,6 @@ class ModelGeneratorTest < Rails::Generators::TestCase
assert_no_migration "db/migrate/create_accounts.rb"
end
- def test_model_with_existent_application_record
- mkdir_p "#{destination_root}/app/models"
- touch "#{destination_root}/app/models/application_record.rb"
-
- Dir.chdir(destination_root) do
- run_generator ["account"]
- end
-
- assert_file "app/models/account.rb", /class Account < ApplicationRecord/
- end
-
def test_plural_names_are_singularized
content = run_generator ["accounts".freeze]
assert_file "app/models/account.rb", /class Account < ApplicationRecord/
diff --git a/railties/test/generators/named_base_test.rb b/railties/test/generators/named_base_test.rb
index 3015b5363b..4e61b660d7 100644
--- a/railties/test/generators/named_base_test.rb
+++ b/railties/test/generators/named_base_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "generators/generators_test_helper"
require "rails/generators/rails/scaffold_controller/scaffold_controller_generator"
@@ -31,6 +33,17 @@ class NamedBaseTest < Rails::Generators::TestCase
assert_name g, "foos", :plural_name
assert_name g, "admin.foo", :i18n_scope
assert_name g, "admin_foos", :table_name
+ assert_name g, "admin/foos", :controller_name
+ assert_name g, %w(admin), :controller_class_path
+ assert_name g, "Admin::Foos", :controller_class_name
+ assert_name g, "admin/foos", :controller_file_path
+ assert_name g, "foos", :controller_file_name
+ assert_name g, "admin.foos", :controller_i18n_scope
+ assert_name g, "admin_foo", :singular_route_name
+ assert_name g, "admin_foos", :plural_route_name
+ assert_name g, "@admin_foo", :redirect_resource_name
+ assert_name g, "admin_foo", :model_resource_name
+ assert_name g, "admin_foos", :index_helper
end
def test_named_generator_attributes_as_ruby
@@ -45,6 +58,17 @@ class NamedBaseTest < Rails::Generators::TestCase
assert_name g, "foos", :plural_name
assert_name g, "admin.foo", :i18n_scope
assert_name g, "admin_foos", :table_name
+ assert_name g, "Admin::Foos", :controller_name
+ assert_name g, %w(admin), :controller_class_path
+ assert_name g, "Admin::Foos", :controller_class_name
+ assert_name g, "admin/foos", :controller_file_path
+ assert_name g, "foos", :controller_file_name
+ assert_name g, "admin.foos", :controller_i18n_scope
+ assert_name g, "admin_foo", :singular_route_name
+ assert_name g, "admin_foos", :plural_route_name
+ assert_name g, "@admin_foo", :redirect_resource_name
+ assert_name g, "admin_foo", :model_resource_name
+ assert_name g, "admin_foos", :index_helper
end
def test_named_generator_attributes_without_pluralized
@@ -57,7 +81,7 @@ class NamedBaseTest < Rails::Generators::TestCase
ActiveRecord::Base.pluralize_table_names = original_pluralize_table_names
end
- def test_scaffold_plural_names
+ def test_namespaced_scaffold_plural_names
g = generator ["admin/foo"]
assert_name g, "admin/foos", :controller_name
assert_name g, %w(admin), :controller_class_path
@@ -67,7 +91,7 @@ class NamedBaseTest < Rails::Generators::TestCase
assert_name g, "admin.foos", :controller_i18n_scope
end
- def test_scaffold_plural_names_as_ruby
+ def test_namespaced_scaffold_plural_names_as_ruby
g = generator ["Admin::Foo"]
assert_name g, "Admin::Foos", :controller_name
assert_name g, %w(admin), :controller_class_path
@@ -129,6 +153,19 @@ class NamedBaseTest < Rails::Generators::TestCase
assert_name g, "admin/foos", :controller_file_path
assert_name g, "foos", :controller_file_name
assert_name g, "admin.foos", :controller_i18n_scope
+ assert_name g, "admin_user", :singular_route_name
+ assert_name g, "admin_users", :plural_route_name
+ assert_name g, "[:admin, @user]", :redirect_resource_name
+ assert_name g, "[:admin, user]", :model_resource_name
+ assert_name g, "admin_users", :index_helper
+ end
+
+ def test_scaffold_plural_names
+ g = generator ["User"]
+ assert_name g, "@user", :redirect_resource_name
+ assert_name g, "user", :model_resource_name
+ assert_name g, "user", :singular_route_name
+ assert_name g, "users", :plural_route_name
end
private
diff --git a/railties/test/generators/namespaced_generators_test.rb b/railties/test/generators/namespaced_generators_test.rb
index 1caabbe6b1..4b75a31f17 100644
--- a/railties/test/generators/namespaced_generators_test.rb
+++ b/railties/test/generators/namespaced_generators_test.rb
@@ -1,8 +1,11 @@
+# frozen_string_literal: true
+
require "generators/generators_test_helper"
require "rails/generators/rails/controller/controller_generator"
require "rails/generators/rails/model/model_generator"
require "rails/generators/mailer/mailer_generator"
require "rails/generators/rails/scaffold/scaffold_generator"
+require "rails/generators/rails/application_record/application_record_generator"
class NamespacedGeneratorTestCase < Rails::Generators::TestCase
include GeneratorsTestHelper
@@ -149,7 +152,7 @@ class NamespacedMailerGeneratorTest < NamespacedGeneratorTestCase
assert_file "app/mailers/test_app/notifier_mailer.rb" do |mailer|
assert_match(/module TestApp/, mailer)
assert_match(/class NotifierMailer < ApplicationMailer/, mailer)
- assert_no_match(/default from: "from@example.com"/, mailer)
+ assert_no_match(/default from: "from@example\.com"/, mailer)
end
end
@@ -421,3 +424,13 @@ class NamespacedScaffoldGeneratorTest < NamespacedGeneratorTestCase
/module TestApp\n class Admin::RolesControllerTest < ActionDispatch::IntegrationTest/
end
end
+
+class NamespacedApplicationRecordGeneratorTest < NamespacedGeneratorTestCase
+ include GeneratorsTestHelper
+ tests Rails::Generators::ApplicationRecordGenerator
+
+ def test_adds_namespace_to_application_record
+ run_generator
+ assert_file "app/models/test_app/application_record.rb", /module TestApp/, / class ApplicationRecord < ActiveRecord::Base/
+ end
+end
diff --git a/railties/test/generators/orm_test.rb b/railties/test/generators/orm_test.rb
index 88ae930554..6eaf2fbfd3 100644
--- a/railties/test/generators/orm_test.rb
+++ b/railties/test/generators/orm_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "generators/generators_test_helper"
require "rails/generators/rails/scaffold_controller/scaffold_controller_generator"
diff --git a/railties/test/generators/plugin_generator_test.rb b/railties/test/generators/plugin_generator_test.rb
index af16a2641a..fc7584c175 100644
--- a/railties/test/generators/plugin_generator_test.rb
+++ b/railties/test/generators/plugin_generator_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "generators/generators_test_helper"
require "rails/generators/rails/plugin/plugin_generator"
require "generators/shared_generator_tests"
@@ -24,6 +26,10 @@ class PluginGeneratorTest < Rails::Generators::TestCase
destination File.join(Rails.root, "tmp/bukkits")
arguments [destination_root]
+ def application_path
+ "#{destination_root}/test/dummy"
+ end
+
# brings setup, teardown, and some tests
include SharedGeneratorTests
@@ -63,16 +69,30 @@ class PluginGeneratorTest < Rails::Generators::TestCase
assert_no_file "config/routes.rb"
assert_no_file "app/assets/config/bukkits_manifest.js"
assert_file "test/test_helper.rb" do |content|
- assert_match(/require.+test\/dummy\/config\/environment/, content)
+ assert_match(/require_relative.+test\/dummy\/config\/environment/, content)
assert_match(/ActiveRecord::Migrator\.migrations_paths.+test\/dummy\/db\/migrate/, content)
assert_match(/Minitest\.backtrace_filter = Minitest::BacktraceFilter\.new/, content)
assert_match(/Rails::TestUnitReporter\.executable = 'bin\/test'/, content)
end
+ assert_file "lib/bukkits/railtie.rb", /module Bukkits\n class Railtie < ::Rails::Railtie\n end\nend/
+ assert_file "lib/bukkits.rb", /require "bukkits\/railtie"/
assert_file "test/bukkits_test.rb", /assert_kind_of Module, Bukkits/
assert_file "bin/test"
assert_no_file "bin/rails"
end
+ def test_generating_in_full_mode_with_almost_of_all_skip_options
+ run_generator [destination_root, "--full", "-M", "-O", "-C", "-S", "-T"]
+ assert_file "bin/rails" do |content|
+ assert_no_match(/\s+require\s+["']rails\/all["']/, content)
+ end
+ assert_file "bin/rails", /#\s+require\s+["']active_record\/railtie["']/
+ assert_file "bin/rails", /#\s+require\s+["']action_mailer\/railtie["']/
+ assert_file "bin/rails", /#\s+require\s+["']action_cable\/engine["']/
+ assert_file "bin/rails", /#\s+require\s+["']sprockets\/railtie["']/
+ assert_file "bin/rails", /#\s+require\s+["']rails\/test_unit\/railtie["']/
+ end
+
def test_generating_test_files_in_full_mode
run_generator [destination_root, "--full"]
assert_directory "test/integration/"
@@ -80,6 +100,11 @@ class PluginGeneratorTest < Rails::Generators::TestCase
assert_file "test/integration/navigation_test.rb", /ActionDispatch::IntegrationTest/
end
+ def test_inclusion_of_git_source
+ run_generator [destination_root]
+ assert_file "Gemfile", /git_source/
+ end
+
def test_inclusion_of_a_debugger
run_generator [destination_root, "--full"]
if defined?(JRUBY_VERSION) || RUBY_ENGINE == "rbx"
@@ -95,23 +120,19 @@ class PluginGeneratorTest < Rails::Generators::TestCase
run_generator [destination_root, "-T", "--full"]
assert_no_directory "test/integration/"
- assert_no_file "test"
+ assert_no_directory "test"
assert_file "Rakefile" do |contents|
assert_no_match(/APP_RAKEFILE/, contents)
end
- end
-
- def test_generating_adds_dummy_app_in_full_mode_without_sprockets
- run_generator [destination_root, "-S", "--full"]
-
- assert_file "test/dummy/config/environments/production.rb" do |contents|
- assert_no_match(/config\.assets/, contents)
+ assert_file "bin/rails" do |contents|
+ assert_no_match(/APP_PATH/, contents)
end
end
def test_generating_adds_dummy_app_rake_tasks_without_unit_test_files
run_generator [destination_root, "-T", "--mountable", "--dummy-path", "my_dummy_app"]
assert_file "Rakefile", /APP_RAKEFILE/
+ assert_file "bin/rails", /APP_PATH/
end
def test_generating_adds_dummy_app_without_javascript_and_assets_deps
@@ -132,8 +153,8 @@ class PluginGeneratorTest < Rails::Generators::TestCase
def test_ensure_that_test_dummy_can_be_generated_from_a_template
FileUtils.cd(Rails.root)
run_generator([destination_root, "-m", "lib/create_test_dummy_template.rb", "--skip-test"])
- assert_file "spec/dummy"
- assert_no_file "test"
+ assert_directory "spec/dummy"
+ assert_no_directory "test"
end
def test_database_entry_is_generated_for_sqlite3_by_default_in_full_mode
@@ -156,47 +177,13 @@ class PluginGeneratorTest < Rails::Generators::TestCase
end
end
- def test_app_generator_without_skips
- run_generator
- assert_file "test/dummy/config/application.rb", /\s+require\s+["']rails\/all["']/
- assert_file "test/dummy/config/environments/development.rb" do |content|
- assert_match(/config\.action_mailer\.raise_delivery_errors = false/, content)
- end
- assert_file "test/dummy/config/environments/test.rb" do |content|
- assert_match(/config\.action_mailer\.delivery_method = :test/, content)
- end
- assert_file "test/dummy/config/environments/production.rb" do |content|
- assert_match(/# config\.action_mailer\.raise_delivery_errors = false/, content)
- end
- end
-
- def test_active_record_is_removed_from_frameworks_if_skip_active_record_is_given
- run_generator [destination_root, "--skip-active-record"]
- assert_file "test/dummy/config/application.rb", /#\s+require\s+["']active_record\/railtie["']/
- end
-
def test_ensure_that_skip_active_record_option_is_passed_to_app_generator
run_generator [destination_root, "--skip_active_record"]
- assert_no_file "test/dummy/config/database.yml"
assert_file "test/test_helper.rb" do |contents|
assert_no_match(/ActiveRecord/, contents)
end
end
- def test_action_mailer_is_removed_from_frameworks_if_skip_action_mailer_is_given
- run_generator [destination_root, "--skip-action-mailer"]
- assert_file "test/dummy/config/application.rb", /#\s+require\s+["']action_mailer\/railtie["']/
- assert_file "test/dummy/config/environments/development.rb" do |content|
- assert_no_match(/config\.action_mailer/, content)
- end
- assert_file "test/dummy/config/environments/test.rb" do |content|
- assert_no_match(/config\.action_mailer/, content)
- end
- assert_file "test/dummy/config/environments/production.rb" do |content|
- assert_no_match(/config\.action_mailer/, content)
- end
- end
-
def test_ensure_that_database_option_is_passed_to_app_generator
run_generator [destination_root, "--database", "postgresql"]
assert_file "test/dummy/config/database.yml", /postgres/
@@ -274,7 +261,7 @@ class PluginGeneratorTest < Rails::Generators::TestCase
assert_file "app/views"
assert_file "app/helpers"
assert_file "app/mailers"
- assert_file "bin/rails"
+ assert_file "bin/rails", /\s+require\s+["']rails\/all["']/
assert_file "config/routes.rb", /Rails.application.routes.draw do/
assert_file "lib/bukkits/engine.rb", /module Bukkits\n class Engine < ::Rails::Engine\n end\nend/
assert_file "lib/bukkits.rb", /require "bukkits\/engine"/
@@ -438,7 +425,7 @@ class PluginGeneratorTest < Rails::Generators::TestCase
assert_file "spec/dummy/config/application.rb"
assert_no_file "test/dummy"
assert_file "test/test_helper.rb" do |content|
- assert_match(/require.+spec\/dummy\/config\/environment/, content)
+ assert_match(/require_relative.+spec\/dummy\/config\/environment/, content)
assert_match(/ActiveRecord::Migrator\.migrations_paths.+spec\/dummy\/db\/migrate/, content)
end
end
@@ -449,17 +436,16 @@ class PluginGeneratorTest < Rails::Generators::TestCase
assert_file "spec/fake/config/application.rb"
assert_no_file "test/dummy"
assert_file "test/test_helper.rb" do |content|
- assert_match(/require.+spec\/fake\/config\/environment/, content)
+ assert_match(/require_relative.+spec\/fake\/config\/environment/, content)
assert_match(/ActiveRecord::Migrator\.migrations_paths.+spec\/fake\/db\/migrate/, content)
end
end
def test_creating_dummy_without_tests_but_with_dummy_path
run_generator [destination_root, "--dummy_path", "spec/dummy", "--skip-test"]
- assert_file "spec/dummy"
- assert_file "spec/dummy/config/application.rb"
- assert_no_file "test"
- assert_no_file "test/test_helper.rb"
+ assert_directory "spec/dummy"
+ assert_file "spec/dummy/config/application.rb", /#\s+require\s+["']rails\/test_unit\/railtie["']/
+ assert_no_directory "test"
assert_file ".gitignore" do |contents|
assert_match(/spec\/dummy/, contents)
end
@@ -488,8 +474,9 @@ class PluginGeneratorTest < Rails::Generators::TestCase
assert_no_file "test/dummy/Gemfile"
assert_no_file "test/dummy/public/robots.txt"
assert_no_file "test/dummy/README.md"
+ assert_no_file "test/dummy/config/master.key"
+ assert_no_file "test/dummy/config/credentials.yml.enc"
assert_no_directory "test/dummy/lib/tasks"
- assert_no_directory "test/dummy/doc"
assert_no_directory "test/dummy/test"
assert_no_directory "test/dummy/vendor"
assert_no_directory "test/dummy/.git"
@@ -497,9 +484,9 @@ class PluginGeneratorTest < Rails::Generators::TestCase
def test_skipping_test_files
run_generator [destination_root, "--skip-test"]
- assert_no_file "test"
+ assert_no_directory "test"
assert_file ".gitignore" do |contents|
- assert_no_match(/test\dummy/, contents)
+ assert_no_match(/test\/dummy/, contents)
end
end
@@ -528,10 +515,11 @@ class PluginGeneratorTest < Rails::Generators::TestCase
gemfile_path = "#{Rails.root}/Gemfile"
Object.const_set("APP_PATH", Rails.root)
FileUtils.touch gemfile_path
+ File.write(gemfile_path, "#foo")
run_generator
- assert_file gemfile_path, /gem 'bukkits', path: 'tmp\/bukkits'/
+ assert_file gemfile_path, /^gem 'bukkits', path: 'tmp\/bukkits'/
ensure
Object.send(:remove_const, "APP_PATH")
FileUtils.rm gemfile_path
@@ -677,20 +665,6 @@ class PluginGeneratorTest < Rails::Generators::TestCase
assert_file "app/models/bukkits/article.rb", /class Article < ApplicationRecord/
end
- def test_generate_application_record_when_does_not_exist_in_mountable_engine
- run_generator [destination_root, "--mountable"]
- FileUtils.rm "#{destination_root}/app/models/bukkits/application_record.rb"
- capture(:stdout) do
- `#{destination_root}/bin/rails g model article`
- end
-
- assert_file "#{destination_root}/app/models/bukkits/application_record.rb" do |record|
- assert_match(/module Bukkits/, record)
- assert_match(/class ApplicationRecord < ActiveRecord::Base/, record)
- assert_match(/self\.abstract_class = true/, record)
- end
- end
-
def test_generate_application_mailer_when_does_not_exist_in_mountable_engine
run_generator [destination_root, "--mountable"]
FileUtils.rm "#{destination_root}/app/mailers/bukkits/application_mailer.rb"
@@ -747,6 +721,38 @@ class PluginGeneratorTest < Rails::Generators::TestCase
Object.send(:remove_const, "ENGINE_ROOT")
end
+ def test_after_bundle_callback
+ path = "http://example.org/rails_template"
+ template = %{ after_bundle { run "echo ran after_bundle" } }.dup
+ template.instance_eval "def read; self; end" # Make the string respond to read
+
+ check_open = -> *args do
+ assert_equal [ path, "Accept" => "application/x-thor-template" ], args
+ template
+ end
+
+ sequence = ["echo ran after_bundle"]
+ @sequence_step ||= 0
+ ensure_bundler_first = -> command do
+ assert_equal sequence[@sequence_step], command, "commands should be called in sequence #{sequence}"
+ @sequence_step += 1
+ end
+
+ content = nil
+ generator([destination_root], template: path).stub(:open, check_open, template) do
+ generator.stub(:bundle_command, ensure_bundler_first) do
+ generator.stub(:run, ensure_bundler_first) do
+ silence_stream($stdout) do
+ content = capture(:stderr) { generator.invoke_all }
+ end
+ end
+ end
+ end
+
+ assert_equal 1, @sequence_step
+ assert_match(/DEPRECATION WARNING: `after_bundle` is deprecated/, content)
+ end
+
private
def action(*args, &block)
diff --git a/railties/test/generators/plugin_test_helper.rb b/railties/test/generators/plugin_test_helper.rb
index 8ac90e3484..528f8d88f9 100644
--- a/railties/test/generators/plugin_test_helper.rb
+++ b/railties/test/generators/plugin_test_helper.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "abstract_unit"
require "tmpdir"
diff --git a/railties/test/generators/plugin_test_runner_test.rb b/railties/test/generators/plugin_test_runner_test.rb
index 0bdd2a77d2..89c3f1e496 100644
--- a/railties/test/generators/plugin_test_runner_test.rb
+++ b/railties/test/generators/plugin_test_runner_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "generators/plugin_test_helper"
class PluginTestRunnerTest < ActiveSupport::TestCase
@@ -71,7 +73,7 @@ class PluginTestRunnerTest < ActiveSupport::TestCase
create_test_file "post", pass: false
output = run_test_command("test/post_test.rb")
- assert_match %r{Finished in.*\n\n1 runs, 1 assertions}, output
+ assert_match %r{Finished in.*\n1 runs, 1 assertions}, output
end
def test_fail_fast
@@ -103,6 +105,12 @@ class PluginTestRunnerTest < ActiveSupport::TestCase
capture(:stderr) { run_test_command("test/models/warnings_test.rb -w") })
end
+ def test_run_rake_test
+ create_test_file "foo"
+ result = Dir.chdir(plugin_path) { `rake test TEST=test/foo_test.rb` }
+ assert_match "1 runs, 1 assertions, 0 failures", result
+ end
+
private
def plugin_path
"#{@destination_root}/bukkits"
diff --git a/railties/test/generators/resource_generator_test.rb b/railties/test/generators/resource_generator_test.rb
index e976e58180..63a2cd3869 100644
--- a/railties/test/generators/resource_generator_test.rb
+++ b/railties/test/generators/resource_generator_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "generators/generators_test_helper"
require "rails/generators/rails/resource/resource_generator"
diff --git a/railties/test/generators/scaffold_controller_generator_test.rb b/railties/test/generators/scaffold_controller_generator_test.rb
index 9971626f9f..fd5aa817b4 100644
--- a/railties/test/generators/scaffold_controller_generator_test.rb
+++ b/railties/test/generators/scaffold_controller_generator_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "generators/generators_test_helper"
require "rails/generators/rails/scaffold_controller/scaffold_controller_generator"
@@ -172,6 +174,29 @@ class ScaffoldControllerGeneratorTest < Rails::Generators::TestCase
assert_instance_method :index, content do |m|
assert_match("@users = User.all", m)
end
+
+ assert_instance_method :create, content do |m|
+ assert_match("redirect_to [:admin, @user]", m)
+ end
+
+ assert_instance_method :update, content do |m|
+ assert_match("redirect_to [:admin, @user]", m)
+ end
+ end
+
+ assert_file "app/views/admin/users/index.html.erb" do |content|
+ assert_match("'Show', [:admin, user]", content)
+ assert_match("'Edit', edit_admin_user_path(user)", content)
+ assert_match("'Destroy', [:admin, user]", content)
+ assert_match("'New User', new_admin_user_path", content)
+ end
+
+ assert_file "app/views/admin/users/new.html.erb" do |content|
+ assert_match("'Back', admin_users_path", content)
+ end
+
+ assert_file "app/views/admin/users/_form.html.erb" do |content|
+ assert_match("model: [:admin, user]", content)
end
end
@@ -182,6 +207,7 @@ class ScaffoldControllerGeneratorTest < Rails::Generators::TestCase
Dir.chdir(engine_path) do
quietly { `bin/rails g controller dashboard foo` }
+ quietly { `bin/rails db:migrate RAILS_ENV=test` }
assert_match(/2 runs, 2 assertions, 0 failures, 0 errors/, `bin/rails test 2>&1`)
end
end
@@ -193,6 +219,7 @@ class ScaffoldControllerGeneratorTest < Rails::Generators::TestCase
Dir.chdir(engine_path) do
quietly { `bin/rails g controller dashboard foo` }
+ quietly { `bin/rails db:migrate RAILS_ENV=test` }
assert_match(/2 runs, 2 assertions, 0 failures, 0 errors/, `bin/rails test 2>&1`)
end
end
diff --git a/railties/test/generators/scaffold_generator_test.rb b/railties/test/generators/scaffold_generator_test.rb
index bc76cead18..b6294c3b94 100644
--- a/railties/test/generators/scaffold_generator_test.rb
+++ b/railties/test/generators/scaffold_generator_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "generators/generators_test_helper"
require "rails/generators/rails/scaffold/scaffold_generator"
@@ -65,6 +67,9 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase
# System tests
assert_file "test/system/product_lines_test.rb" do |test|
assert_match(/class ProductLinesTest < ApplicationSystemTestCase/, test)
+ assert_match(/visit product_lines_url/, test)
+ assert_match(/fill_in "Title", with: @product_line\.title/, test)
+ assert_match(/assert_text "Product line was successfully updated"/, test)
end
# Views
@@ -146,6 +151,9 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase
assert_no_match(/assert_redirected_to/, test)
end
+ # System tests
+ assert_no_file "test/system/product_lines_test.rb"
+
# Views
assert_no_file "app/views/layouts/product_lines.html.erb"
@@ -173,6 +181,16 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase
end
end
+ def test_system_tests_without_attributes
+ run_generator ["product_line"]
+
+ assert_file "test/system/product_lines_test.rb" do |content|
+ assert_match(/class ProductLinesTest < ApplicationSystemTestCase/, content)
+ assert_match(/test "visiting the index"/, content)
+ assert_no_match(/fill_in/, content)
+ end
+ end
+
def test_scaffold_on_revoke
run_generator
run_generator ["product_line"], behavior: :revoke
@@ -192,6 +210,9 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase
assert_no_file "app/controllers/product_lines_controller.rb"
assert_no_file "test/controllers/product_lines_controller_test.rb"
+ # System tests
+ assert_no_file "test/system/product_lines_test.rb"
+
# Views
assert_no_file "app/views/product_lines"
assert_no_file "app/views/layouts/product_lines.html.erb"
@@ -257,8 +278,18 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase
assert_file "test/controllers/admin/roles_controller_test.rb",
/class Admin::RolesControllerTest < ActionDispatch::IntegrationTest/
+ assert_file "test/system/admin/roles_test.rb",
+ /class Admin::RolesTest < ApplicationSystemTestCase/
+
# Views
- %w(index edit new show _form).each do |view|
+ assert_file "app/views/admin/roles/index.html.erb" do |content|
+ assert_match("'Show', admin_role", content)
+ assert_match("'Edit', edit_admin_role_path(admin_role)", content)
+ assert_match("'Destroy', admin_role", content)
+ assert_match("'New Admin Role', new_admin_role_path", content)
+ end
+
+ %w(edit new show _form).each do |view|
assert_file "app/views/admin/roles/#{view}.html.erb"
end
assert_no_file "app/views/layouts/admin/roles.html.erb"
@@ -292,6 +323,9 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase
assert_no_file "app/controllers/admin/roles_controller.rb"
assert_no_file "test/controllers/admin/roles_controller_test.rb"
+ # System tests
+ assert_no_file "test/system/admin/roles_test.rb"
+
# Views
assert_no_file "app/views/admin/roles"
assert_no_file "app/views/layouts/admin/roles.html.erb"
@@ -478,6 +512,11 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase
assert_match(/password_confirmation: 'secret'/, content)
end
+ assert_file "test/system/users_test.rb" do |content|
+ assert_match(/fill_in "Password", with: 'secret'/, content)
+ assert_match(/fill_in "Password Confirmation", with: 'secret'/, content)
+ end
+
assert_file "test/fixtures/users.yml" do |content|
assert_match(/password_digest: <%= BCrypt::Password.create\('secret'\) %>/, content)
end
@@ -573,6 +612,8 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase
assert File.exist?("app/controllers/bukkits/users_controller.rb")
assert File.exist?("test/controllers/bukkits/users_controller_test.rb")
+ assert File.exist?("test/system/bukkits/users_test.rb")
+
assert File.exist?("app/views/bukkits/users/index.html.erb")
assert File.exist?("app/views/bukkits/users/edit.html.erb")
assert File.exist?("app/views/bukkits/users/show.html.erb")
@@ -601,6 +642,8 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase
assert_not File.exist?("app/controllers/bukkits/users_controller.rb")
assert_not File.exist?("test/controllers/bukkits/users_controller_test.rb")
+ assert_not File.exist?("test/system/bukkits/users_test.rb")
+
assert_not File.exist?("app/views/bukkits/users/index.html.erb")
assert_not File.exist?("app/views/bukkits/users/edit.html.erb")
assert_not File.exist?("app/views/bukkits/users/show.html.erb")
diff --git a/railties/test/generators/shared_generator_tests.rb b/railties/test/generators/shared_generator_tests.rb
index 5e75879964..6b746f3fed 100644
--- a/railties/test/generators/shared_generator_tests.rb
+++ b/railties/test/generators/shared_generator_tests.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
#
# Tests, setup, and teardown common to the application and plugin generator suites.
#
@@ -20,6 +22,10 @@ module SharedGeneratorTests
Rails.application = TestApp::Application.instance
end
+ def application_path
+ destination_root
+ end
+
def test_skeleton_is_created
run_generator
@@ -77,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!" }
+ template = %{ say "It works!" }.dup
template.instance_eval "def read; self; end" # Make the string respond to read
check_open = -> *args do
@@ -121,4 +127,247 @@ module SharedGeneratorTests
assert_no_file("app/models/concerns/.keep")
end
+
+ def test_default_frameworks_are_required_when_others_are_removed
+ run_generator [
+ destination_root,
+ "--skip-active-record",
+ "--skip-active-storage",
+ "--skip-action-mailer",
+ "--skip-action-cable",
+ "--skip-sprockets"
+ ]
+
+ assert_file "#{application_path}/config/application.rb", /^require\s+["']rails["']/
+ assert_file "#{application_path}/config/application.rb", /^require\s+["']active_model\/railtie["']/
+ assert_file "#{application_path}/config/application.rb", /^require\s+["']active_job\/railtie["']/
+ assert_file "#{application_path}/config/application.rb", /^# require\s+["']active_record\/railtie["']/
+ assert_file "#{application_path}/config/application.rb", /^# require\s+["']active_storage\/engine["']/
+ assert_file "#{application_path}/config/application.rb", /^require\s+["']action_controller\/railtie["']/
+ assert_file "#{application_path}/config/application.rb", /^# require\s+["']action_mailer\/railtie["']/
+ assert_file "#{application_path}/config/application.rb", /^require\s+["']action_view\/railtie["']/
+ assert_file "#{application_path}/config/application.rb", /^# require\s+["']action_cable\/engine["']/
+ assert_file "#{application_path}/config/application.rb", /^# require\s+["']sprockets\/railtie["']/
+ assert_file "#{application_path}/config/application.rb", /^require\s+["']rails\/test_unit\/railtie["']/
+ end
+
+ def test_generator_without_skips
+ run_generator
+ assert_file "#{application_path}/config/application.rb", /\s+require\s+["']rails\/all["']/
+ assert_file "#{application_path}/config/environments/development.rb" do |content|
+ assert_match(/config\.action_mailer\.raise_delivery_errors = false/, content)
+ end
+ assert_file "#{application_path}/config/environments/test.rb" do |content|
+ assert_match(/config\.action_mailer\.delivery_method = :test/, content)
+ end
+ assert_file "#{application_path}/config/environments/production.rb" do |content|
+ assert_match(/# config\.action_mailer\.raise_delivery_errors = false/, content)
+ assert_match(/^ # config\.require_master_key = true/, content)
+ end
+ end
+
+ def test_gitignore_when_sqlite3
+ run_generator
+
+ assert_file ".gitignore" do |content|
+ assert_match(/sqlite3/, content)
+ end
+ end
+
+ def test_gitignore_when_non_sqlite3_db
+ run_generator([destination_root, "-d", "mysql"])
+
+ assert_file ".gitignore" do |content|
+ assert_no_match(/sqlite/i, content)
+ end
+ end
+
+ def test_generator_if_skip_active_record_is_given
+ run_generator [destination_root, "--skip-active-record"]
+ assert_no_directory "#{application_path}/db/"
+ assert_no_file "#{application_path}/config/database.yml"
+ assert_no_file "#{application_path}/app/models/application_record.rb"
+ assert_file "#{application_path}/config/application.rb", /#\s+require\s+["']active_record\/railtie["']/
+ assert_file "test/test_helper.rb" do |helper_content|
+ assert_no_match(/fixtures :all/, helper_content)
+ end
+ assert_file "#{application_path}/bin/setup" do |setup_content|
+ assert_no_match(/db:setup/, setup_content)
+ end
+ assert_file "#{application_path}/bin/update" do |update_content|
+ assert_no_match(/db:migrate/, update_content)
+ end
+ assert_file ".gitignore" do |content|
+ assert_no_match(/sqlite/i, content)
+ end
+ end
+
+ def test_generator_for_active_storage
+ run_generator
+
+ assert_file "#{application_path}/app/assets/javascripts/application.js" do |content|
+ assert_match(/^\/\/= require activestorage/, content)
+ end
+
+ assert_file "#{application_path}/config/environments/development.rb" do |content|
+ assert_match(/config\.active_storage/, content)
+ end
+
+ assert_file "#{application_path}/config/environments/production.rb" do |content|
+ assert_match(/config\.active_storage/, content)
+ end
+
+ assert_file "#{application_path}/config/environments/test.rb" do |content|
+ assert_match(/config\.active_storage/, content)
+ end
+
+ assert_file "#{application_path}/config/storage.yml"
+ assert_directory "#{application_path}/storage"
+ assert_directory "#{application_path}/tmp/storage"
+
+ assert_file ".gitignore" do |content|
+ assert_match(/\/storage\//, content)
+ end
+ end
+
+ def test_generator_if_skip_active_storage_is_given
+ run_generator [destination_root, "--skip-active-storage"]
+
+ 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)
+ end
+
+ assert_file "#{application_path}/config/environments/development.rb" do |content|
+ assert_no_match(/config\.active_storage/, content)
+ end
+
+ assert_file "#{application_path}/config/environments/production.rb" do |content|
+ assert_no_match(/config\.active_storage/, content)
+ end
+
+ assert_file "#{application_path}/config/environments/test.rb" do |content|
+ assert_no_match(/config\.active_storage/, content)
+ end
+
+ assert_no_file "#{application_path}/config/storage.yml"
+ assert_no_directory "#{application_path}/db/migrate"
+ assert_no_directory "#{application_path}/storage"
+ assert_no_directory "#{application_path}/tmp/storage"
+
+ assert_file ".gitignore" do |content|
+ assert_no_match(/\/storage\//, content)
+ end
+ end
+
+ def test_generator_does_not_generate_active_storage_contents_if_skip_active_record_is_given
+ run_generator [destination_root, "--skip-active-record"]
+
+ 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)
+ end
+
+ assert_file "#{application_path}/config/environments/development.rb" do |content|
+ assert_no_match(/config\.active_storage/, content)
+ end
+
+ assert_file "#{application_path}/config/environments/production.rb" do |content|
+ assert_no_match(/config\.active_storage/, content)
+ end
+
+ assert_file "#{application_path}/config/environments/test.rb" do |content|
+ assert_no_match(/config\.active_storage/, content)
+ end
+
+ assert_no_file "#{application_path}/config/storage.yml"
+ assert_no_directory "#{application_path}/db/migrate"
+ assert_no_directory "#{application_path}/storage"
+ assert_no_directory "#{application_path}/tmp/storage"
+
+ assert_file ".gitignore" do |content|
+ assert_no_match(/\/storage\//, content)
+ end
+ end
+
+ def test_generator_if_skip_action_mailer_is_given
+ run_generator [destination_root, "--skip-action-mailer"]
+ assert_file "#{application_path}/config/application.rb", /#\s+require\s+["']action_mailer\/railtie["']/
+ assert_file "#{application_path}/config/environments/development.rb" do |content|
+ assert_no_match(/config\.action_mailer/, content)
+ end
+ assert_file "#{application_path}/config/environments/test.rb" do |content|
+ assert_no_match(/config\.action_mailer/, content)
+ end
+ assert_file "#{application_path}/config/environments/production.rb" do |content|
+ assert_no_match(/config\.action_mailer/, content)
+ end
+ assert_no_directory "#{application_path}/app/mailers"
+ assert_no_directory "#{application_path}/test/mailers"
+ end
+
+ def test_generator_if_skip_action_cable_is_given
+ 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_directory "#{application_path}/app/channels"
+ assert_file "Gemfile" do |content|
+ assert_no_match(/redis/, content)
+ end
+ end
+
+ def test_generator_if_skip_sprockets_is_given
+ run_generator [destination_root, "--skip-sprockets"]
+
+ assert_no_file "#{application_path}/config/initializers/assets.rb"
+
+ assert_file "#{application_path}/config/application.rb", /#\s+require\s+["']sprockets\/railtie["']/
+
+ 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|
+ assert_no_match(/config\.assets\.debug/, content)
+ end
+
+ 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
+ end
+
+ def test_generator_for_yarn
+ run_generator
+ assert_file "#{application_path}/package.json", /dependencies/
+ assert_file "#{application_path}/config/initializers/assets.rb", /node_modules/
+
+ assert_file ".gitignore" do |content|
+ assert_match(/node_modules/, content)
+ assert_match(/yarn-error\.log/, content)
+ end
+ end
+
+ def test_generator_for_yarn_skipped
+ run_generator([destination_root, "--skip-yarn"])
+ assert_no_file "#{application_path}/package.json"
+ assert_no_file "#{application_path}/bin/yarn"
+
+ assert_file "#{application_path}/config/initializers/assets.rb" do |content|
+ assert_no_match(/node_modules/, content)
+ end
+
+ assert_file ".gitignore" do |content|
+ assert_no_match(/node_modules/, content)
+ assert_no_match(/yarn-error\.log/, content)
+ end
+ end
end
diff --git a/railties/test/generators/system_test_generator_test.rb b/railties/test/generators/system_test_generator_test.rb
index 4622360244..efa70a050b 100644
--- a/railties/test/generators/system_test_generator_test.rb
+++ b/railties/test/generators/system_test_generator_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "generators/generators_test_helper"
require "rails/generators/rails/system_test/system_test_generator"
diff --git a/railties/test/generators/task_generator_test.rb b/railties/test/generators/task_generator_test.rb
index 2285534bb9..5f162919d8 100644
--- a/railties/test/generators/task_generator_test.rb
+++ b/railties/test/generators/task_generator_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "generators/generators_test_helper"
require "rails/generators/rails/task/task_generator"
diff --git a/railties/test/generators/test_runner_in_engine_test.rb b/railties/test/generators/test_runner_in_engine_test.rb
index 680dc2608e..0e15b5e388 100644
--- a/railties/test/generators/test_runner_in_engine_test.rb
+++ b/railties/test/generators/test_runner_in_engine_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "generators/plugin_test_helper"
class TestRunnerInEngineTest < ActiveSupport::TestCase
diff --git a/railties/test/generators_test.rb b/railties/test/generators_test.rb
index b784446535..1735804664 100644
--- a/railties/test/generators_test.rb
+++ b/railties/test/generators_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "generators/generators_test_helper"
require "rails/generators/rails/model/model_generator"
require "rails/generators/test_unit/model/model_generator"
@@ -34,6 +36,19 @@ class GeneratorsTest < Rails::Generators::TestCase
assert_match "Maybe you meant 'migration'", output
end
+ def test_generator_suggestions_except_en_locale
+ orig_available_locales = I18n.available_locales
+ orig_default_locale = I18n.default_locale
+ I18n.available_locales = :ja
+ I18n.default_locale = :ja
+ name = :tas
+ output = capture(:stdout) { Rails::Generators.invoke name }
+ assert_match "Maybe you meant 'task', 'job' or", output
+ ensure
+ I18n.available_locales = orig_available_locales
+ I18n.default_locale = orig_default_locale
+ end
+
def test_generator_multiple_suggestions
name = :tas
output = capture(:stdout) { Rails::Generators.invoke name }
@@ -124,7 +139,7 @@ class GeneratorsTest < Rails::Generators::TestCase
def test_rails_generators_help_does_not_include_app_nor_plugin_new
output = capture(:stdout) { Rails::Generators.help }
- assert_no_match(/app/, output)
+ assert_no_match(/app\W/, output)
assert_no_match(/[^:]plugin/, output)
end
@@ -233,7 +248,7 @@ class GeneratorsTest < Rails::Generators::TestCase
end
def test_usage_with_embedded_ruby
- require File.expand_path("fixtures/lib/generators/usage_template/usage_template_generator", __dir__)
+ require_relative "fixtures/lib/generators/usage_template/usage_template_generator"
output = capture(:stdout) { Rails::Generators.invoke :usage_template, ["--help"] }
assert_match(/:: 2 ::/, output)
end
diff --git a/railties/test/initializable_test.rb b/railties/test/initializable_test.rb
index 4b67c91cc5..59fee245f9 100644
--- a/railties/test/initializable_test.rb
+++ b/railties/test/initializable_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "abstract_unit"
require "rails/initializable"
diff --git a/railties/test/isolation/abstract_unit.rb b/railties/test/isolation/abstract_unit.rb
index 7496b5f84a..7522237a38 100644
--- a/railties/test/isolation/abstract_unit.rb
+++ b/railties/test/isolation/abstract_unit.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Note:
# It is important to keep this file as light as possible
# the goal for tests that require this is to test booting up
@@ -54,10 +56,7 @@ module TestHelpers
@app ||= begin
ENV["RAILS_ENV"] = env
- # FIXME: shush Sass warning spam, not relevant to testing Railties
- Kernel.silence_warnings do
- require "#{app_path}/config/environment"
- end
+ require "#{app_path}/config/environment"
Rails.application
end
@@ -66,7 +65,7 @@ module TestHelpers
end
def extract_body(response)
- "".tap do |body|
+ "".dup.tap do |body|
response[2].each { |chunk| body << chunk }
end
end
@@ -106,7 +105,6 @@ module TestHelpers
def build_app(options = {})
@prev_rails_env = ENV["RAILS_ENV"]
ENV["RAILS_ENV"] = "development"
- ENV["SECRET_KEY_BASE"] ||= SecureRandom.hex(16)
FileUtils.rm_rf(app_path)
FileUtils.cp_r(app_template_path, app_path)
@@ -155,6 +153,7 @@ module TestHelpers
def teardown_app
ENV["RAILS_ENV"] = @prev_rails_env if @prev_rails_env
+ FileUtils.rm_rf(tmp_path)
end
# Make a very basic app, without creating the whole directory structure.
@@ -164,9 +163,10 @@ module TestHelpers
require "action_controller/railtie"
require "action_view/railtie"
- @app = Class.new(Rails::Application)
+ @app = Class.new(Rails::Application) do
+ def self.name; "RailtiesTestApp"; end
+ end
@app.config.eager_load = false
- @app.secrets.secret_key_base = "3b7cd727ee24e8444053437c36cc66c4"
@app.config.session_store :cookie_store, key: "_myapp_session"
@app.config.active_support.deprecation = :log
@app.config.active_support.test_order = :random
@@ -222,8 +222,8 @@ module TestHelpers
FileUtils.mkdir_p(dir)
app = File.readlines("#{app_path}/config/application.rb")
- app.insert(2, "$:.unshift(\"#{dir}/lib\")")
- app.insert(3, "require #{name.inspect}")
+ app.insert(4, "$:.unshift(\"#{dir}/lib\")")
+ app.insert(5, "require #{name.inspect}")
File.open("#{app_path}/config/application.rb", "r+") do |f|
f.puts app
@@ -234,10 +234,86 @@ module TestHelpers
end
end
- def script(script)
- Dir.chdir(app_path) do
- `#{Gem.ruby} #{app_path}/bin/rails #{script}`
+ # Invoke a bin/rails command inside the app
+ #
+ # allow_failure:: true to return normally if the command exits with
+ # a non-zero status. By default, this method will raise.
+ # stderr:: true to pass STDERR output straight to the "real" STDERR.
+ # By default, the STDERR and STDOUT of the process will be
+ # combined in the returned string.
+ def rails(*args, allow_failure: false, stderr: false)
+ args = args.flatten
+ fork = true
+
+ command = "bin/rails #{Shellwords.join args}#{' 2>&1' unless stderr}"
+
+ # Don't fork if the environment has disabled it
+ fork = false if ENV["NO_FORK"]
+
+ # Don't fork if the runtime isn't able to
+ fork = false if !Process.respond_to?(:fork)
+
+ # Don't fork if we're re-invoking minitest
+ fork = false if args.first == "t" || args.grep(/\Atest(:|\z)/).any?
+
+ if fork
+ out_read, out_write = IO.pipe
+ if stderr
+ err_read, err_write = IO.pipe
+ else
+ err_write = out_write
+ end
+
+ pid = fork do
+ out_read.close
+ err_read.close if err_read
+
+ $stdin.reopen(File::NULL, "r")
+ $stdout.reopen(out_write)
+ $stderr.reopen(err_write)
+
+ at_exit do
+ case $!
+ when SystemExit
+ exit! $!.status
+ when nil
+ exit! 0
+ else
+ err_write.puts "#{$!.class}: #{$!}"
+ exit! 1
+ end
+ end
+
+ Rails.instance_variable_set :@_env, nil
+
+ $-v = $-w = false
+ Dir.chdir app_path unless Dir.pwd == app_path
+
+ ARGV.replace(args)
+ load "./bin/rails"
+
+ exit! 0
+ end
+
+ out_write.close
+
+ if err_read
+ err_write.close
+
+ $stderr.write err_read.read
+ end
+
+ output = out_read.read
+
+ Process.waitpid pid
+
+ else
+ output = `cd #{app_path}; #{command}`
end
+
+ raise "rails command failed (#{$?.exitstatus}): #{command}\n#{output}" unless allow_failure || $?.success?
+
+ output
end
def add_to_top_of_config(str)
@@ -297,7 +373,7 @@ module TestHelpers
end
def use_frameworks(arr)
- to_remove = [:actionmailer, :activerecord] - arr
+ to_remove = [:actionmailer, :activerecord, :activestorage, :activejob] - arr
if to_remove.include?(:activerecord)
remove_from_config "config.active_record.*"
@@ -313,8 +389,6 @@ class ActiveSupport::TestCase
include TestHelpers::Rack
include TestHelpers::Generation
include ActiveSupport::Testing::Stream
-
- self.test_order = :sorted
end
# Create a scope and build a fixture rails app
@@ -329,4 +403,25 @@ Module.new do
File.open("#{app_template_path}/config/boot.rb", "w") do |f|
f.puts "require 'rails/all'"
end
+
+ # 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 }")
+ File.write("#{app_template_path}/config/application.rb", contents)
+
+ require "rails"
+
+ require "active_model"
+ require "active_job"
+ require "active_record"
+ require "action_controller"
+ require "action_mailer"
+ require "action_view"
+ require "active_storage"
+ require "action_cable"
+ require "sprockets"
+
+ require "action_view/helpers"
+ require "action_dispatch/routing/route_set"
end unless defined?(RAILS_ISOLATED_ENGINE)
diff --git a/railties/test/json_params_parsing_test.rb b/railties/test/json_params_parsing_test.rb
index 7fff3bb465..65ad9673ff 100644
--- a/railties/test/json_params_parsing_test.rb
+++ b/railties/test/json_params_parsing_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "abstract_unit"
require "action_dispatch"
require "active_record"
diff --git a/railties/test/path_generation_test.rb b/railties/test/path_generation_test.rb
index c0b03d0c15..849b183b37 100644
--- a/railties/test/path_generation_test.rb
+++ b/railties/test/path_generation_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "abstract_unit"
require "active_support/core_ext/object/with_options"
require "active_support/core_ext/object/json"
@@ -56,12 +58,14 @@ class PathGenerationTest < ActiveSupport::TestCase
Rails.logger = Logger.new nil
app = Class.new(Rails::Application) {
+ def self.name; "ScriptNameTestApp"; end
+
attr_accessor :controller
+
def initialize
super
app = self
@routes = TestSet.new ->(c) { app.controller = c }
- secrets.secret_key_base = "foo"
secrets.secret_token = "foo"
end
def app; routes; end
diff --git a/railties/test/paths_test.rb b/railties/test/paths_test.rb
index f3db0a51d2..854b4448a4 100644
--- a/railties/test/paths_test.rb
+++ b/railties/test/paths_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "abstract_unit"
require "rails/paths"
require "minitest/mock"
diff --git a/railties/test/rack_logger_test.rb b/railties/test/rack_logger_test.rb
index 33b4bc6a3a..e47f30d5b6 100644
--- a/railties/test/rack_logger_test.rb
+++ b/railties/test/rack_logger_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "abstract_unit"
require "active_support/testing/autorun"
require "active_support/test_case"
diff --git a/railties/test/rails_info_controller_test.rb b/railties/test/rails_info_controller_test.rb
index d795629ccd..878a238f8d 100644
--- a/railties/test/rails_info_controller_test.rb
+++ b/railties/test/rails_info_controller_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "abstract_unit"
module ActionController
diff --git a/railties/test/rails_info_test.rb b/railties/test/rails_info_test.rb
index 383adcc55d..43b60b9144 100644
--- a/railties/test/rails_info_test.rb
+++ b/railties/test/rails_info_test.rb
@@ -1,19 +1,8 @@
-require "abstract_unit"
-
-unless defined?(Rails) && defined?(Rails::Info)
- module Rails
- class Info; end
- end
-end
+# frozen_string_literal: true
-require "active_support/core_ext/kernel/reporting"
+require "abstract_unit"
class InfoTest < ActiveSupport::TestCase
- def setup
- Rails.send :remove_const, :Info
- silence_warnings { load "rails/info.rb" }
- end
-
def test_property_with_block_swallows_exceptions_and_ignores_property
assert_nothing_raised do
Rails::Info.module_eval do
diff --git a/railties/test/railties/engine_test.rb b/railties/test/railties/engine_test.rb
index e382a7a873..fc710feb63 100644
--- a/railties/test/railties/engine_test.rb
+++ b/railties/test/railties/engine_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
require "stringio"
require "rack/test"
@@ -30,6 +32,11 @@ module RailtiesTest
require "#{app_path}/config/environment"
end
+ def migrations
+ migration_root = File.expand_path(ActiveRecord::Migrator.migrations_paths.first, app_path)
+ ActiveRecord::Migrator.migrations(migration_root)
+ end
+
test "serving sprocket's assets" do
@plugin.write "app/assets/javascripts/engine.js.erb", "<%= :alert %>();"
add_to_env_config "development", "config.assets.digest = false"
@@ -80,31 +87,32 @@ module RailtiesTest
end
RUBY
- add_to_config "ActiveRecord::Base.timestamped_migrations = false"
-
boot_rails
Dir.chdir(app_path) do
+ # Install Active Storage migration file first so as not to affect test.
+ `bundle exec rake active_storage:install`
output = `bundle exec rake bukkits:install:migrations`
- assert File.exist?("#{app_path}/db/migrate/2_create_users.bukkits.rb")
- assert File.exist?("#{app_path}/db/migrate/3_add_last_name_to_users.bukkits.rb")
- assert_match(/Copied migration 2_create_users\.bukkits\.rb from bukkits/, output)
- assert_match(/Copied migration 3_add_last_name_to_users\.bukkits\.rb from bukkits/, output)
- assert_match(/NOTE: Migration 3_create_sessions\.rb from bukkits has been skipped/, output)
- assert_equal 3, Dir["#{app_path}/db/migrate/*.rb"].length
-
- output = `bundle exec rake railties:install:migrations`.split("\n")
+ ["CreateUsers", "AddLastNameToUsers", "CreateSessions"].each do |migration_name|
+ assert migrations.detect { |migration| migration.name == migration_name }
+ end
+ assert_match(/Copied migration \d+_create_users\.bukkits\.rb from bukkits/, output)
+ assert_match(/Copied migration \d+_add_last_name_to_users\.bukkits\.rb from bukkits/, output)
+ assert_match(/NOTE: Migration \d+_create_sessions\.rb from bukkits has been skipped/, output)
- assert_no_match(/2_create_users/, output.join("\n"))
+ migrations_count = Dir["#{app_path}/db/migrate/*.rb"].length
- bukkits_migration_order = output.index(output.detect { |o| /NOTE: Migration 3_create_sessions\.rb from bukkits has been skipped/ =~ o })
- assert_not_nil bukkits_migration_order, "Expected migration to be skipped"
+ assert_equal migrations.length, migrations_count
- migrations_count = Dir["#{app_path}/db/migrate/*.rb"].length
- `bundle exec rake railties:install:migrations`
+ output = `bundle exec rake railties:install:migrations`.split("\n")
assert_equal migrations_count, Dir["#{app_path}/db/migrate/*.rb"].length
+
+ assert_no_match(/\d+_create_users/, output.join("\n"))
+
+ bukkits_migration_order = output.index(output.detect { |o| /NOTE: Migration \d+_create_sessions\.rb from bukkits has been skipped/ =~ o })
+ assert_not_nil bukkits_migration_order, "Expected migration to be skipped"
end
end
@@ -136,7 +144,7 @@ module RailtiesTest
output = `bundle exec rake railties:install:migrations`.split("\n")
assert_match(/Copied migration \d+_create_users\.bukkits\.rb from bukkits/, output.first)
- assert_match(/Copied migration \d+_create_blogs\.blog_engine\.rb from blog_engine/, output.last)
+ assert_match(/Copied migration \d+_create_blogs\.blog_engine\.rb from blog_engine/, output.second)
end
end
@@ -169,10 +177,12 @@ module RailtiesTest
boot_rails
Dir.chdir(app_path) do
+ # Install Active Storage migration file first so as not to affect test.
+ `bundle exec rake active_storage:install`
output = `bundle exec rake railties:install:migrations`.split("\n")
assert_match(/Copied migration \d+_create_users\.core_engine\.rb from core_engine/, output.first)
- assert_match(/Copied migration \d+_create_keys\.api_engine\.rb from api_engine/, output.last)
+ assert_match(/Copied migration \d+_create_keys\.api_engine\.rb from api_engine/, output.second)
end
end
@@ -201,9 +211,12 @@ module RailtiesTest
Dir.chdir(@plugin.path) do
output = `bundle exec rake app:bukkits:install:migrations`
- assert File.exist?("#{app_path}/db/migrate/0_add_first_name_to_users.bukkits.rb")
- assert_match(/Copied migration 0_add_first_name_to_users\.bukkits\.rb from bukkits/, output)
- assert_equal 1, Dir["#{app_path}/db/migrate/*.rb"].length
+
+ migration_with_engine_path = migrations.detect { |migration| migration.name == "AddFirstNameToUsers" }
+ assert migration_with_engine_path
+ assert_match(/\/db\/migrate\/\d+_add_first_name_to_users\.bukkits\.rb/, migration_with_engine_path.filename)
+ assert_match(/Copied migration \d+_add_first_name_to_users\.bukkits\.rb from bukkits/, output)
+ assert_equal migrations.length, Dir["#{app_path}/db/migrate/*.rb"].length
end
end
@@ -503,7 +516,7 @@ YAML
def call(env)
response = @app.call(env)
- response[2].each(&:upcase!)
+ response[2] = response[2].collect(&:upcase)
response
end
end
@@ -882,7 +895,17 @@ YAML
end
RUBY
- add_to_config "isolate_namespace AppTemplate"
+ engine "loaded_first" do |plugin|
+ plugin.write "lib/loaded_first.rb", <<-RUBY
+ module AppTemplate
+ module LoadedFirst
+ class Engine < ::Rails::Engine
+ isolate_namespace(AppTemplate)
+ end
+ end
+ end
+ RUBY
+ end
app_file "config/routes.rb", <<-RUBY
Rails.application.routes.draw do end
@@ -890,7 +913,7 @@ YAML
boot_rails
- assert_equal AppTemplate::Engine, AppTemplate.railtie_namespace
+ assert_equal AppTemplate::LoadedFirst::Engine, AppTemplate.railtie_namespace
end
test "properly reload routes" do
@@ -1285,10 +1308,10 @@ YAML
boot_rails
- get("/bukkits/bukkit", {}, "SCRIPT_NAME" => "/foo")
+ get("/bukkits/bukkit", {}, { "SCRIPT_NAME" => "/foo" })
assert_equal "/foo/bar", last_response.body
- get("/bar", {}, "SCRIPT_NAME" => "/foo")
+ get("/bar", {}, { "SCRIPT_NAME" => "/foo" })
assert_equal "/foo/bukkits/bukkit", last_response.body
end
@@ -1334,13 +1357,128 @@ YAML
boot_rails
- get("/bukkits/bukkit", {}, "SCRIPT_NAME" => "/foo")
+ get("/bukkits/bukkit", {}, { "SCRIPT_NAME" => "/foo" })
assert_equal "/foo/bar", last_response.body
- get("/bar", {}, "SCRIPT_NAME" => "/foo")
+ get("/bar", {}, { "SCRIPT_NAME" => "/foo" })
assert_equal "/foo/bukkits/bukkit", last_response.body
end
+ test "isolated engine can be mounted under multiple static locations" do
+ app_file "app/controllers/foos_controller.rb", <<-RUBY
+ class FoosController < ApplicationController
+ def through_fruits
+ render plain: fruit_bukkits.posts_path
+ end
+
+ def through_vegetables
+ render plain: vegetable_bukkits.posts_path
+ end
+ end
+ RUBY
+
+ app_file "config/routes.rb", <<-RUBY
+ Rails.application.routes.draw do
+ scope "/fruits" do
+ mount Bukkits::Engine => "/bukkits", as: :fruit_bukkits
+ end
+
+ scope "/vegetables" do
+ mount Bukkits::Engine => "/bukkits", as: :vegetable_bukkits
+ end
+
+ get "/through_fruits" => "foos#through_fruits"
+ get "/through_vegetables" => "foos#through_vegetables"
+ end
+ RUBY
+
+ @plugin.write "config/routes.rb", <<-RUBY
+ Bukkits::Engine.routes.draw do
+ resources :posts, only: :index
+ end
+ RUBY
+
+ boot_rails
+
+ get("/through_fruits")
+ assert_equal "/fruits/bukkits/posts", last_response.body
+
+ get("/through_vegetables")
+ assert_equal "/vegetables/bukkits/posts", last_response.body
+ end
+
+ test "isolated engine can be mounted under multiple dynamic locations" do
+ app_file "app/controllers/foos_controller.rb", <<-RUBY
+ class FoosController < ApplicationController
+ def through_fruits
+ render plain: fruit_bukkits.posts_path(fruit_id: 1)
+ end
+
+ def through_vegetables
+ render plain: vegetable_bukkits.posts_path(vegetable_id: 1)
+ end
+ end
+ RUBY
+
+ app_file "config/routes.rb", <<-RUBY
+ Rails.application.routes.draw do
+ resources :fruits do
+ mount Bukkits::Engine => "/bukkits"
+ end
+
+ resources :vegetables do
+ mount Bukkits::Engine => "/bukkits"
+ end
+
+ get "/through_fruits" => "foos#through_fruits"
+ get "/through_vegetables" => "foos#through_vegetables"
+ end
+ RUBY
+
+ @plugin.write "config/routes.rb", <<-RUBY
+ Bukkits::Engine.routes.draw do
+ resources :posts, only: :index
+ end
+ RUBY
+
+ boot_rails
+
+ get("/through_fruits")
+ assert_equal "/fruits/1/bukkits/posts", last_response.body
+
+ get("/through_vegetables")
+ assert_equal "/vegetables/1/bukkits/posts", last_response.body
+ end
+
+ test "route helpers resolve script name correctly when called with different script name from current one" do
+ @plugin.write "app/controllers/posts_controller.rb", <<-RUBY
+ class PostsController < ActionController::Base
+ def index
+ render plain: fruit_bukkits.posts_path(fruit_id: 2)
+ end
+ end
+ RUBY
+
+ app_file "config/routes.rb", <<-RUBY
+ Rails.application.routes.draw do
+ resources :fruits do
+ mount Bukkits::Engine => "/bukkits"
+ end
+ end
+ RUBY
+
+ @plugin.write "config/routes.rb", <<-RUBY
+ Bukkits::Engine.routes.draw do
+ resources :posts, only: :index
+ end
+ RUBY
+
+ boot_rails
+
+ get("/fruits/1/bukkits/posts")
+ assert_equal "/fruits/2/bukkits/posts", last_response.body
+ end
+
private
def app
Rails.application
diff --git a/railties/test/railties/generators_test.rb b/railties/test/railties/generators_test.rb
index 5c691b9ec4..8383cb3050 100644
--- a/railties/test/railties/generators_test.rb
+++ b/railties/test/railties/generators_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
RAILS_ISOLATED_ENGINE = true
require "isolation/abstract_unit"
diff --git a/railties/test/railties/mounted_engine_test.rb b/railties/test/railties/mounted_engine_test.rb
index 6639e55382..48f0fbc80f 100644
--- a/railties/test/railties/mounted_engine_test.rb
+++ b/railties/test/railties/mounted_engine_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
module ApplicationTests
@@ -111,6 +113,7 @@ module ApplicationTests
@plugin.write "config/routes.rb", <<-RUBY
Blog::Engine.routes.draw do
resources :posts
+ get '/different_context', to: 'posts#different_context'
get '/generate_application_route', to: 'posts#generate_application_route'
get '/application_route_in_view', to: 'posts#application_route_in_view'
get '/engine_polymorphic_path', to: 'posts#engine_polymorphic_path'
@@ -125,6 +128,10 @@ module ApplicationTests
render plain: blog.post_path(1)
end
+ def different_context
+ render plain: blog.post_path(1, user: "ada")
+ end
+
def generate_application_route
path = main_app.url_for(controller: "/main",
action: "index",
@@ -196,8 +203,12 @@ module ApplicationTests
get "/john/blog/posts"
assert_equal "/john/blog/posts/1", last_response.body
+ # test generating engine route from engine with a different context
+ get "/john/blog/different_context"
+ assert_equal "/ada/blog/posts/1", last_response.body
+
# test generating engine's route from engine with default_url_options
- get "/john/blog/posts", {}, "SCRIPT_NAME" => "/foo"
+ get "/john/blog/posts", {}, { "SCRIPT_NAME" => "/foo" }
assert_equal "/foo/john/blog/posts/1", last_response.body
# test generating engine's route from application
@@ -211,10 +222,10 @@ module ApplicationTests
assert_equal "/john/blog/posts", last_response.body
# test generating engine's route from application with default_url_options
- get "/engine_route", {}, "SCRIPT_NAME" => "/foo"
+ get "/engine_route", {}, { "SCRIPT_NAME" => "/foo" }
assert_equal "/foo/anonymous/blog/posts", last_response.body
- get "/url_for_engine_route", {}, "SCRIPT_NAME" => "/foo"
+ get "/url_for_engine_route", {}, { "SCRIPT_NAME" => "/foo" }
assert_equal "/foo/john/blog/posts", last_response.body
# test generating application's route from engine
@@ -232,14 +243,14 @@ module ApplicationTests
assert_equal "/anonymous/blog/posts/1", last_response.body
# test generating engine's route from other engine with default_url_options
- get "/metrics/generate_blog_route", {}, "SCRIPT_NAME" => "/foo"
+ get "/metrics/generate_blog_route", {}, { "SCRIPT_NAME" => "/foo" }
assert_equal "/foo/anonymous/blog/posts/1", last_response.body
- get "/metrics/generate_blog_route_in_view", {}, "SCRIPT_NAME" => "/foo"
+ get "/metrics/generate_blog_route_in_view", {}, { "SCRIPT_NAME" => "/foo" }
assert_equal "/foo/anonymous/blog/posts/1", last_response.body
# test generating application's route from engine with default_url_options
- get "/someone/blog/generate_application_route", {}, "SCRIPT_NAME" => "/foo"
+ get "/someone/blog/generate_application_route", {}, { "SCRIPT_NAME" => "/foo" }
assert_equal "/foo/", last_response.body
# test polymorphic routes
diff --git a/railties/test/railties/railtie_test.rb b/railties/test/railties/railtie_test.rb
index 30cd525266..359ab0fdae 100644
--- a/railties/test/railties/railtie_test.rb
+++ b/railties/test/railties/railtie_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
module RailtiesTest
diff --git a/railties/test/secrets_test.rb b/railties/test/secrets_test.rb
index 36c8ef1fd9..06877bc76a 100644
--- a/railties/test/secrets_test.rb
+++ b/railties/test/secrets_test.rb
@@ -1,29 +1,24 @@
-require "abstract_unit"
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
-require "rails/generators"
-require "rails/generators/rails/encrypted_secrets/encrypted_secrets_generator"
require "rails/secrets"
class Rails::SecretsTest < ActiveSupport::TestCase
include ActiveSupport::Testing::Isolation
- def setup
- build_app
- end
-
- def teardown
- teardown_app
- end
+ setup :build_app
+ teardown :teardown_app
test "setting read to false skips parsing" do
run_secrets_generator do
Rails::Secrets.write(<<-end_of_secrets)
- test:
+ production:
yeah_yeah: lets-walk-in-the-cool-evening-light
end_of_secrets
- Rails.application.config.read_encrypted_secrets = false
- Rails.application.instance_variable_set(:@secrets, nil) # Dance around caching 💃🕺
+ add_to_env_config("production", "config.read_encrypted_secrets = false")
+ app("production")
+
assert_not Rails.application.secrets.yeah_yeah
end
end
@@ -45,7 +40,7 @@ class Rails::SecretsTest < ActiveSupport::TestCase
ENV["RAILS_MASTER_KEY"] = IO.binread("config/secrets.yml.key").strip
FileUtils.rm("config/secrets.yml.key")
- assert_match "production:\n# external_api_key", Rails::Secrets.read
+ assert_match "# production:\n# external_api_key:", Rails::Secrets.read
ensure
ENV["RAILS_MASTER_KEY"] = old_key
end
@@ -67,7 +62,7 @@ class Rails::SecretsTest < ActiveSupport::TestCase
Rails::Secrets.read_for_editing do |tmp_path|
decrypted_path = tmp_path
- assert_match(/production:\n# external_api_key/, File.read(tmp_path))
+ assert_match(/# production:\n# external_api_key/, File.read(tmp_path))
File.write(tmp_path, "Empty streets, empty nights. The Downtown Lights.")
end
@@ -80,18 +75,18 @@ class Rails::SecretsTest < ActiveSupport::TestCase
test "merging secrets with encrypted precedence" do
run_secrets_generator do
File.write("config/secrets.yml", <<-end_of_secrets)
- test:
+ production:
yeah_yeah: lets-go-walking-down-this-empty-street
end_of_secrets
Rails::Secrets.write(<<-end_of_secrets)
- test:
+ production:
yeah_yeah: lets-walk-in-the-cool-evening-light
end_of_secrets
- Rails.application.config.root = app_path
- Rails.application.config.read_encrypted_secrets = true
- Rails.application.instance_variable_set(:@secrets, nil) # Dance around caching 💃🕺
+ add_to_env_config("production", "config.read_encrypted_secrets = true")
+ app("production")
+
assert_equal "lets-walk-in-the-cool-evening-light", Rails.application.secrets.yeah_yeah
end
end
@@ -107,16 +102,75 @@ class Rails::SecretsTest < ActiveSupport::TestCase
config.dereferenced_secret = Rails.application.secrets.some_secret
end_of_config
- assert_equal "yeah yeah\n", `bin/rails runner -e production "puts Rails.application.config.dereferenced_secret"`
+ app("production")
+
+ assert_equal "yeah yeah", Rails.application.config.dereferenced_secret
+ end
+ end
+
+ test "do not update secrets.yml.enc when secretes do not change" do
+ run_secrets_generator do
+ Rails::Secrets.read_for_editing do |tmp_path|
+ File.write(tmp_path, "Empty streets, empty nights. The Downtown Lights.")
+ end
+
+ FileUtils.cp("config/secrets.yml.enc", "config/secrets.yml.enc.bk")
+
+ Rails::Secrets.read_for_editing do |tmp_path|
+ File.write(tmp_path, "Empty streets, empty nights. The Downtown Lights.")
+ end
+
+ assert_equal File.read("config/secrets.yml.enc.bk"), File.read("config/secrets.yml.enc")
+ end
+ end
+
+ test "can read secrets written in binary" do
+ run_secrets_generator do
+ secrets = <<-end_of_secrets
+ production:
+ api_key: 00112233445566778899aabbccddeeff…
+ end_of_secrets
+
+ Rails::Secrets.write(secrets.dup.force_encoding(Encoding::ASCII_8BIT))
+
+ Rails::Secrets.read_for_editing do |tmp_path|
+ assert_match(/production:\n\s*api_key: 00112233445566778899aabbccddeeff…\n/, File.read(tmp_path))
+ end
+
+ app("production")
+
+ assert_equal "00112233445566778899aabbccddeeff…", Rails.application.secrets.api_key
+ end
+ end
+
+ test "can read secrets written in non-binary" do
+ run_secrets_generator do
+ secrets = <<-end_of_secrets
+ production:
+ api_key: 00112233445566778899aabbccddeeff…
+ end_of_secrets
+
+ Rails::Secrets.write(secrets)
+
+ Rails::Secrets.read_for_editing do |tmp_path|
+ assert_equal(secrets.dup.force_encoding(Encoding::ASCII_8BIT), IO.binread(tmp_path))
+ end
+
+ app("production")
+
+ assert_equal "00112233445566778899aabbccddeeff…", Rails.application.secrets.api_key
end
end
private
def run_secrets_generator
Dir.chdir(app_path) do
- capture(:stdout) do
- Rails::Generators::EncryptedSecretsGenerator.start
- end
+ File.write("config/secrets.yml.key", "f731758c639da2604dfb6bf3d1025de8")
+ File.write("config/secrets.yml.enc", "sEB0mHxDbeP1/KdnMk00wyzPFACl9K6t0cZWn5/Mfx/YbTHvnI07vrneqHg9kaH3wOS7L6pIQteu1P077OtE4BSx/ZRc/sgQPHyWu/tXsrfHqnPNpayOF/XZqizE91JacSFItNMWpuPsp9ynbzz+7cGhoB1S4aPNIU6u0doMrzdngDbijsaAFJmsHIQh6t/QHoJx--8aMoE0PvUWmw1Iqz--ldFqnM/K0g9k17M8PKoN/Q==")
+
+ add_to_config <<-RUBY
+ config.read_encrypted_secrets = true
+ RUBY
yield
end
diff --git a/railties/test/test_unit/reporter_test.rb b/railties/test/test_unit/reporter_test.rb
index 98201394cd..ad852d0f35 100644
--- a/railties/test/test_unit/reporter_test.rb
+++ b/railties/test/test_unit/reporter_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "abstract_unit"
require "rails/test_unit/reporter"
require "minitest/mock"
@@ -70,7 +72,7 @@ class TestUnitReporterTest < ActiveSupport::TestCase
@reporter.record(errored_test)
@reporter.report
- expect = %r{\AE\n\nError:\nTestUnitReporterTest::ExampleTest#woot:\nArgumentError: wups\n No backtrace\n\nbin/rails test .*test/test_unit/reporter_test\.rb:\d+\n\n\z}
+ expect = %r{\AE\n\nError:\nTestUnitReporterTest::ExampleTest#woot:\nArgumentError: wups\n \n\nbin/rails test .*test/test_unit/reporter_test\.rb:\d+\n\n\z}
assert_match expect, @output.string
end
@@ -150,7 +152,7 @@ class TestUnitReporterTest < ActiveSupport::TestCase
colored = Rails::TestUnitReporter.new @output, color: true, output_inline: true
colored.record(errored_test)
- expected = %r{\e\[31mE\e\[0m\n\n\e\[31mError:\nTestUnitReporterTest::ExampleTest#woot:\nArgumentError: wups\n No backtrace\n\e\[0m}
+ expected = %r{\e\[31mE\e\[0m\n\n\e\[31mError:\nTestUnitReporterTest::ExampleTest#woot:\nArgumentError: wups\n \n\e\[0m}
assert_match expected, @output.string
end
end
@@ -171,8 +173,11 @@ class TestUnitReporterTest < ActiveSupport::TestCase
end
def errored_test
+ error = ArgumentError.new("wups")
+ error.set_backtrace([ "some_test.rb:4" ])
+
et = ExampleTest.new(:woot)
- et.failures << Minitest::UnexpectedError.new(ArgumentError.new("wups"))
+ et.failures << Minitest::UnexpectedError.new(error)
et
end
diff --git a/railties/test/version_test.rb b/railties/test/version_test.rb
index 86a482e091..17a024fe7f 100644
--- a/railties/test/version_test.rb
+++ b/railties/test/version_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "abstract_unit"
class VersionTest < ActiveSupport::TestCase