aboutsummaryrefslogtreecommitdiffstats
path: root/railties
diff options
context:
space:
mode:
Diffstat (limited to 'railties')
-rw-r--r--railties/CHANGELOG.md89
-rw-r--r--railties/MIT-LICENSE2
-rw-r--r--railties/lib/rails.rb1
-rw-r--r--railties/lib/rails/application.rb73
-rw-r--r--railties/lib/rails/application/configuration.rb17
-rw-r--r--railties/lib/rails/application/default_middleware_stack.rb10
-rw-r--r--railties/lib/rails/application/finisher.rb2
-rw-r--r--railties/lib/rails/application_controller.rb16
-rw-r--r--railties/lib/rails/commands/dbconsole.rb17
-rw-r--r--railties/lib/rails/commands/plugin.rb14
-rw-r--r--railties/lib/rails/commands/runner.rb19
-rw-r--r--railties/lib/rails/engine.rb1
-rw-r--r--railties/lib/rails/generators/actions.rb16
-rw-r--r--railties/lib/rails/generators/app_base.rb64
-rw-r--r--railties/lib/rails/generators/base.rb2
-rw-r--r--railties/lib/rails/generators/erb.rb6
-rw-r--r--railties/lib/rails/generators/erb/controller/controller_generator.rb6
-rw-r--r--railties/lib/rails/generators/erb/mailer/mailer_generator.rb4
-rw-r--r--railties/lib/rails/generators/erb/mailer/templates/view.html.erb5
-rw-r--r--railties/lib/rails/generators/erb/scaffold/scaffold_generator.rb6
-rw-r--r--railties/lib/rails/generators/rails/app/app_generator.rb10
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/application.rb7
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/databases/frontbase.yml5
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/databases/ibm_db.yml5
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/databases/jdbc.yml5
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml6
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/databases/jdbcpostgresql.yml16
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/databases/jdbcsqlite3.yml5
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/databases/mysql.yml11
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/databases/oracle.yml5
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml22
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/databases/sqlite3.yml9
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/databases/sqlserver.yml5
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt5
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt2
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/secrets.yml (renamed from railties/lib/rails/generators/rails/app/templates/config/initializers/secret_token.rb.tt)14
-rw-r--r--railties/lib/rails/generators/rails/app/templates/test/test_helper.rb2
-rw-r--r--railties/lib/rails/generators/rails/plugin/templates/Gemfile2
-rw-r--r--railties/lib/rails/generators/rails/resource_route/resource_route_generator.rb2
-rw-r--r--railties/lib/rails/generators/test_unit/mailer/mailer_generator.rb9
-rw-r--r--railties/lib/rails/generators/test_unit/mailer/templates/preview.rb13
-rw-r--r--railties/lib/rails/generators/testing/behaviour.rb16
-rw-r--r--railties/lib/rails/info_controller.rb18
-rw-r--r--railties/lib/rails/mailers_controller.rb73
-rw-r--r--railties/lib/rails/paths.rb2
-rw-r--r--railties/lib/rails/railtie.rb6
-rw-r--r--railties/lib/rails/templates/layouts/application.html.erb2
-rw-r--r--railties/lib/rails/templates/rails/mailers/email.html.erb98
-rw-r--r--railties/lib/rails/templates/rails/mailers/index.html.erb8
-rw-r--r--railties/lib/rails/templates/rails/mailers/mailer.html.erb6
-rw-r--r--railties/lib/rails/test_help.rb4
-rw-r--r--railties/lib/rails/test_unit/testing.rake1
-rw-r--r--railties/lib/rails/version.rb2
-rw-r--r--railties/lib/rails/welcome_controller.rb7
-rw-r--r--railties/test/abstract_unit.rb2
-rw-r--r--railties/test/application/configuration_test.rb92
-rw-r--r--railties/test/application/initializers/frameworks_test.rb2
-rw-r--r--railties/test/application/initializers/i18n_test.rb45
-rw-r--r--railties/test/application/mailer_previews_test.rb428
-rw-r--r--railties/test/application/middleware/session_test.rb2
-rw-r--r--railties/test/application/middleware_test.rb2
-rw-r--r--railties/test/application/rake/dbs_test.rb20
-rw-r--r--railties/test/application/rake_test.rb10
-rw-r--r--railties/test/application/test_test.rb47
-rw-r--r--railties/test/commands/dbconsole_test.rb96
-rw-r--r--railties/test/configuration/middleware_stack_proxy_test.rb4
-rw-r--r--railties/test/generators/app_generator_test.rb116
-rw-r--r--railties/test/generators/generators_test_helper.rb8
-rw-r--r--railties/test/generators/mailer_generator_test.rb57
-rw-r--r--railties/test/generators/plugin_generator_test.rb21
-rw-r--r--railties/test/generators/shared_generator_tests.rb16
-rw-r--r--railties/test/isolation/abstract_unit.rb24
-rw-r--r--railties/test/rails_info_controller_test.rb2
73 files changed, 1523 insertions, 244 deletions
diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md
index 21ac596ab9..21887c32fe 100644
--- a/railties/CHANGELOG.md
+++ b/railties/CHANGELOG.md
@@ -1,3 +1,88 @@
+* `test_help.rb` now automatically checks/maintains your test datbase
+ schema. (Use `config.active_record.maintain_test_schema = false` to
+ disable.)
+
+ *Jon Leighton*
+
+* Configure `secrets.yml` and `database.yml` to read configuration
+ from the system environment by default for production.
+
+ *José Valim*
+
+* `config.assets.raise_runtime_errors` is set to true by default
+
+ This option has been introduced in
+ [sprockets-rails#100][https://github.com/rails/sprockets-rails/pull/100]
+ and defaults to true in new applications in development.
+
+ *Richard Schneeman*
+
+* Generates `html` and `text` templates for mailers by default.
+
+ *Kassio Borges*
+
+* Move `secret_key_base` from `config/initializers/secret_token.rb`
+ to `config/secrets.yml`.
+
+ `secret_key_base` is now saved in `Rails.application.secrets.secret_key_base`
+ and it fallbacks to the value of `config.secret_key_base` when it is not
+ present in `config/secrets.yml`.
+
+ `config/initializers/secret_token.rb` is not generated by default
+ in new applications.
+
+ *Guillermo Iguaran*
+
+* Generate a new `secrets.yml` file in the `config` folder for new
+ applications. By default, this file contains the application's `secret_key_base`,
+ but it could also be used to store other secrets such as access keys for external
+ APIs.
+
+ The secrets added to this file will be accessible via `Rails.application.secrets`.
+ For example, with the following `secrets.yml`:
+
+ development:
+ secret_key_base: 3b7cd727ee24e8444053437c36cc66c3
+ some_api_key: SOMEKEY
+
+ `Rails.application.secrets.some_api_key` will return `SOMEKEY` in the development
+ environment.
+
+ *Guillermo Iguaran*
+
+* Add `ENV['DATABASE_URL']` support in `rails dbconsole`. Fixes #13320.
+
+ *Huiming Teo*
+
+* Add `Application#message_verifier` method to return a message verifier.
+
+ This verifier can be used to generate and verify signed messages in the application.
+
+ message = Rails.application.message_verifier(:sensitive_data).generate('my sensible data')
+ Rails.application.message_verifier(:sensitive_data).verify(message)
+ # => 'my sensible data'
+
+ It is recommended not to use the same verifier for different things, so you can get different
+ verifiers passing the name argument.
+
+ message = Rails.application.message_verifier(:cookies).generate('my sensible cookie data')
+
+ See the `ActiveSupport::MessageVerifier` documentation for more information.
+
+ *Rafael Mendonça França*
+
+* The [Spring application
+ preloader](https://github.com/jonleighton/spring) is now installed
+ by default for new applications. It uses the development group of
+ the Gemfile, so will not be installed in production.
+
+ *Jon Leighton*
+
+* Uses .railsrc while creating new plugin if it is available.
+ Fixes #10700.
+
+ *Prathamesh Sonpatki*
+
* Remove turbolinks when generating a new application based on a template that skips it.
Example:
@@ -148,11 +233,11 @@
*Paul Nikitochkin*
* Remove deprecated `ActiveRecord::Generators::ActiveModel#update_attributes` in
- favor of `ActiveRecord::Generators::ActiveModel#update`
+ favor of `ActiveRecord::Generators::ActiveModel#update`.
*Vipul A M*
-* Remove deprecated `config.whiny_nils` option
+* Remove deprecated `config.whiny_nils` option.
*Vipul A M*
diff --git a/railties/MIT-LICENSE b/railties/MIT-LICENSE
index 0d7fb865e2..2950f05b11 100644
--- a/railties/MIT-LICENSE
+++ b/railties/MIT-LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2004-2013 David Heinemeier Hansson
+Copyright (c) 2004-2014 David Heinemeier Hansson
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
diff --git a/railties/lib/rails.rb b/railties/lib/rails.rb
index ea82327365..be7570a5ba 100644
--- a/railties/lib/rails.rb
+++ b/railties/lib/rails.rb
@@ -25,6 +25,7 @@ module Rails
autoload :Info
autoload :InfoController
+ autoload :MailersController
autoload :WelcomeController
class << self
diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb
index d1e88cfafd..05acd78d98 100644
--- a/railties/lib/rails/application.rb
+++ b/railties/lib/rails/application.rb
@@ -1,6 +1,8 @@
require 'fileutils'
+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 'rails/engine'
module Rails
@@ -103,16 +105,17 @@ module Rails
delegate :default_url_options, :default_url_options=, to: :routes
INITIAL_VARIABLES = [:config, :railties, :routes_reloader, :reloaders,
- :routes, :helpers, :app_env_config] # :nodoc:
+ :routes, :helpers, :app_env_config, :secrets] # :nodoc:
def initialize(initial_variable_values = {}, &block)
super()
- @initialized = false
- @reloaders = []
- @routes_reloader = nil
- @app_env_config = nil
- @ordered_railties = nil
- @railties = nil
+ @initialized = false
+ @reloaders = []
+ @routes_reloader = nil
+ @app_env_config = nil
+ @ordered_railties = nil
+ @railties = nil
+ @message_verifiers = {}
add_lib_to_load_path!
ActiveSupport.run_load_hooks(:before_configuration, self)
@@ -149,8 +152,8 @@ 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 ||= begin
- if config.secret_key_base
- key_generator = ActiveSupport::KeyGenerator.new(config.secret_key_base, iterations: 1000)
+ if secrets.secret_key_base
+ key_generator = ActiveSupport::KeyGenerator.new(secrets.secret_key_base, iterations: 1000)
ActiveSupport::CachingKeyGenerator.new(key_generator)
else
ActiveSupport::LegacyKeyGenerator.new(config.secret_token)
@@ -158,6 +161,31 @@ module Rails
end
end
+ # Returns a message verifier object.
+ #
+ # This verifier can be used to generate and verify signed messages in the application.
+ #
+ # It is recommended not to use the same verifier for different things, so you can get different
+ # verifiers passing the +verifier_name+ argument.
+ #
+ # ==== Parameters
+ #
+ # * +verifier_name+ - the name of the message verifier.
+ #
+ # ==== Examples
+ #
+ # message = Rails.application.message_verifier('sensitive_data').generate('my sensible data')
+ # Rails.application.message_verifier('sensitive_data').verify(message)
+ # # => 'my sensible data'
+ #
+ # See the +ActiveSupport::MessageVerifier+ documentation for more information.
+ def message_verifier(verifier_name)
+ @message_verifiers[verifier_name] ||= begin
+ secret = key_generator.generate_key(verifier_name.to_s)
+ ActiveSupport::MessageVerifier.new(secret)
+ end
+ end
+
# Stores some of the Rails initial environment parameters which
# will be used by middlewares and engines to configure themselves.
def env_config
@@ -168,7 +196,7 @@ module Rails
"action_dispatch.parameter_filter" => config.filter_parameters,
"action_dispatch.redirect_filter" => config.filter_redirect,
"action_dispatch.secret_token" => config.secret_token,
- "action_dispatch.secret_key_base" => config.secret_key_base,
+ "action_dispatch.secret_key_base" => secrets.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,
@@ -273,6 +301,27 @@ module Rails
@config = configuration
end
+ def secrets #:nodoc:
+ @secrets ||= begin
+ secrets = ActiveSupport::OrderedOptions.new
+ yaml = config.paths["config/secrets"].first
+ if File.exist?(yaml)
+ require "erb"
+ env_secrets = YAML.load(ERB.new(IO.read(yaml)).result)[Rails.env]
+ secrets.merge!(env_secrets.symbolize_keys) if env_secrets
+ end
+
+ # Fallback to config.secret_key_base if secrets.secret_key_base isn't set
+ secrets.secret_key_base ||= config.secret_key_base
+
+ secrets
+ end
+ end
+
+ def secrets=(secrets) #:nodoc:
+ @secrets = secrets
+ end
+
def to_app #:nodoc:
self
end
@@ -364,8 +413,8 @@ module Rails
end
def validate_secret_key_config! #:nodoc:
- if config.secret_key_base.blank? && config.secret_token.blank?
- raise "You must set config.secret_key_base in your app's config."
+ if secrets.secret_key_base.blank? && config.secret_token.blank?
+ raise "Missing `secret_key_base` for '#{Rails.env}' environment, set this value in `config/secrets.yml`"
end
end
end
diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb
index dd0b9c6d70..e902205a13 100644
--- a/railties/lib/rails/application/configuration.rb
+++ b/railties/lib/rails/application/configuration.rb
@@ -76,6 +76,7 @@ module Rails
@paths ||= begin
paths = super
paths.add "config/database", with: "config/database.yml"
+ paths.add "config/secrets", with: "config/secrets.yml"
paths.add "config/environment", with: "config/environment.rb"
paths.add "lib/templates"
paths.add "log", with: "log/#{Rails.env}.log"
@@ -87,17 +88,23 @@ module Rails
end
end
- # Loads and returns the configuration of the database.
+ # Loads and returns the entire raw configuration of database from
+ # values stored in `config/database.yml`.
def database_configuration
- yaml = paths["config/database"].first
- if File.exist?(yaml)
+ yaml = Pathname.new(paths["config/database"].first || "")
+
+ config = if yaml.exist?
require "erb"
- YAML.load ERB.new(IO.read(yaml)).result
+ YAML.load(ERB.new(yaml.read).result) || {}
elsif ENV['DATABASE_URL']
- nil
+ # Value from ENV['DATABASE_URL'] is set to default database connection
+ # by Active Record.
+ {}
else
raise "Could not load database configuration. No such file - #{yaml}"
end
+
+ config
rescue Psych::SyntaxError => e
raise "YAML syntax error occurred while parsing #{paths["config/database"].first}. " \
"Please note that YAML must be consistently indented using spaces. Tabs are not allowed. " \
diff --git a/railties/lib/rails/application/default_middleware_stack.rb b/railties/lib/rails/application/default_middleware_stack.rb
index 570ff02c83..a00afe008c 100644
--- a/railties/lib/rails/application/default_middleware_stack.rb
+++ b/railties/lib/rails/application/default_middleware_stack.rb
@@ -11,11 +11,6 @@ module Rails
def build_stack
ActionDispatch::MiddlewareStack.new.tap do |middleware|
- if rack_cache = load_rack_cache
- require "action_dispatch/http/rack_cache"
- middleware.use ::Rack::Cache, rack_cache
- end
-
if config.force_ssl
middleware.use ::ActionDispatch::SSL, config.ssl_options
end
@@ -26,6 +21,11 @@ module Rails
middleware.use ::ActionDispatch::Static, paths["public"].first, config.static_cache_control
end
+ if rack_cache = load_rack_cache
+ require "action_dispatch/http/rack_cache"
+ middleware.use ::Rack::Cache, rack_cache
+ end
+
middleware.use ::Rack::Lock unless allow_concurrency?
middleware.use ::Rack::Runtime
middleware.use ::Rack::MethodOverride
diff --git a/railties/lib/rails/application/finisher.rb b/railties/lib/rails/application/finisher.rb
index 7a1bb1e25c..5b8509b2e9 100644
--- a/railties/lib/rails/application/finisher.rb
+++ b/railties/lib/rails/application/finisher.rb
@@ -22,6 +22,8 @@ module Rails
initializer :add_builtin_route do |app|
if Rails.env.development?
app.routes.append do
+ get '/rails/mailers' => "rails/mailers#index"
+ get '/rails/mailers/*path' => "rails/mailers#preview"
get '/rails/info/properties' => "rails/info#properties"
get '/rails/info/routes' => "rails/info#routes"
get '/rails/info' => "rails/info#index"
diff --git a/railties/lib/rails/application_controller.rb b/railties/lib/rails/application_controller.rb
new file mode 100644
index 0000000000..9a29ec21cf
--- /dev/null
+++ b/railties/lib/rails/application_controller.rb
@@ -0,0 +1,16 @@
+class Rails::ApplicationController < ActionController::Base # :nodoc:
+ self.view_paths = File.expand_path('../templates', __FILE__)
+ layout 'application'
+
+ protected
+
+ def require_local!
+ unless local_request?
+ render text: '<p>For security purposes, this information is only available to local requests.</p>', status: :forbidden
+ end
+ end
+
+ def local_request?
+ Rails.application.config.consider_all_requests_local || request.local?
+ end
+end
diff --git a/railties/lib/rails/commands/dbconsole.rb b/railties/lib/rails/commands/dbconsole.rb
index 3e4cc787c4..f6d8aec30d 100644
--- a/railties/lib/rails/commands/dbconsole.rb
+++ b/railties/lib/rails/commands/dbconsole.rb
@@ -81,14 +81,11 @@ module Rails
def config
@config ||= begin
- cfg = begin
- YAML.load(ERB.new(IO.read("config/database.yml")).result)
- rescue SyntaxError, StandardError
- require APP_PATH
- Rails.application.config.database_configuration
+ if configurations[environment].blank?
+ raise ActiveRecord::AdapterNotSpecified, "'#{environment}' database is not configured. Available configuration: #{configurations.inspect}"
+ else
+ configurations[environment]
end
-
- cfg[environment] || abort("No database is configured for the environment '#{environment}'")
end
end
@@ -102,6 +99,12 @@ module Rails
protected
+ def configurations
+ require APP_PATH
+ ActiveRecord::Base.configurations = Rails.application.config.database_configuration
+ ActiveRecord::Base.configurations
+ end
+
def parse_arguments(arguments)
options = {}
diff --git a/railties/lib/rails/commands/plugin.rb b/railties/lib/rails/commands/plugin.rb
index 837fe0ec10..f7a0b99005 100644
--- a/railties/lib/rails/commands/plugin.rb
+++ b/railties/lib/rails/commands/plugin.rb
@@ -2,6 +2,20 @@ if ARGV.first != "new"
ARGV[0] = "--help"
else
ARGV.shift
+ unless ARGV.delete("--no-rc")
+ customrc = ARGV.index{ |x| x.include?("--rc=") }
+ railsrc = if customrc
+ File.expand_path(ARGV.delete_at(customrc).gsub(/--rc=/, ""))
+ else
+ File.join(File.expand_path("~"), '.railsrc')
+ end
+ if File.exist?(railsrc)
+ extra_args_string = File.read(railsrc)
+ extra_args = extra_args_string.split(/\n+/).map {|l| l.split}.flatten
+ puts "Using #{extra_args.join(" ")} from #{railsrc}"
+ ARGV.insert(1, *extra_args)
+ end
+ end
end
require 'rails/generators'
diff --git a/railties/lib/rails/commands/runner.rb b/railties/lib/rails/commands/runner.rb
index dd2ee5639e..3a71f8d3f8 100644
--- a/railties/lib/rails/commands/runner.rb
+++ b/railties/lib/rails/commands/runner.rb
@@ -9,7 +9,7 @@ if ARGV.first.nil?
end
ARGV.clone.options do |opts|
- opts.banner = "Usage: rails runner [options] ('Some.ruby(code)' or a filename)"
+ opts.banner = "Usage: rails runner [options] [<'Some.ruby(code)'> | <filename.rb>]"
opts.separator ""
@@ -22,14 +22,23 @@ ARGV.clone.options do |opts|
opts.on("-h", "--help",
"Show this help message.") { $stdout.puts opts; exit }
+ opts.separator ""
+ opts.separator "Examples: "
+
+ opts.separator " rails runner 'puts Rails.env'"
+ opts.separator " This runs the code `puts Rails.env` after loading the app"
+ opts.separator ""
+ opts.separator " rails runner path/to/filename.rb"
+ opts.separator " This runs the Ruby file located at `path/to/filename.rb` after loading the app"
+
if RbConfig::CONFIG['host_os'] !~ /mswin|mingw/
opts.separator ""
opts.separator "You can also use runner as a shebang line for your executables:"
- opts.separator "-------------------------------------------------------------"
- opts.separator "#!/usr/bin/env #{File.expand_path($0)} runner"
+ opts.separator " -------------------------------------------------------------"
+ opts.separator " #!/usr/bin/env #{File.expand_path($0)} runner"
opts.separator ""
- opts.separator "Product.all.each { |p| p.price *= 2 ; p.save! }"
- opts.separator "-------------------------------------------------------------"
+ opts.separator " Product.all.each { |p| p.price *= 2 ; p.save! }"
+ opts.separator " -------------------------------------------------------------"
end
opts.order! { |o| code_or_file ||= o } rescue retry
diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb
index 54a0f1c002..5c54cdaa70 100644
--- a/railties/lib/rails/engine.rb
+++ b/railties/lib/rails/engine.rb
@@ -2,7 +2,6 @@ require 'rails/railtie'
require 'rails/engine/railties'
require 'active_support/core_ext/module/delegation'
require 'pathname'
-require 'rbconfig'
module Rails
# <tt>Rails::Engine</tt> allows you to wrap a specific Rails application or subset of
diff --git a/railties/lib/rails/generators/actions.rb b/railties/lib/rails/generators/actions.rb
index 366c72ebaa..afdbf5c241 100644
--- a/railties/lib/rails/generators/actions.rb
+++ b/railties/lib/rails/generators/actions.rb
@@ -9,7 +9,7 @@ module Rails
@in_group = nil
end
- # Adds an entry into Gemfile for the supplied gem.
+ # Adds an entry into +Gemfile+ for the supplied gem.
#
# gem "rspec", group: :test
# gem "technoweenie-restful-authentication", lib: "restful-authentication", source: "http://gems.github.com/"
@@ -61,7 +61,7 @@ module Rails
end
end
- # Add the given source to Gemfile
+ # Add the given source to +Gemfile+
#
# add_source "http://gems.github.com/"
def add_source(source, options={})
@@ -72,10 +72,10 @@ module Rails
end
end
- # Adds a line inside the Application class for config/application.rb.
+ # Adds a line inside the Application class for <tt>config/application.rb</tt>.
#
- # If options :env is specified, the line is appended to the corresponding
- # file in config/environments.
+ # If options <tt>:env</tt> is specified, the line is appended to the corresponding
+ # file in <tt>config/environments</tt>.
#
# environment do
# "config.autoload_paths += %W(#{config.root}/extras)"
@@ -116,7 +116,7 @@ module Rails
end
end
- # Create a new file in the vendor/ directory. Code can be specified
+ # Create a new file in the <tt>vendor/</tt> directory. Code can be specified
# in a block or a data string can be given.
#
# vendor("sekrit.rb") do
@@ -143,7 +143,7 @@ module Rails
create_file("lib/#{filename}", data, verbose: false, &block)
end
- # Create a new Rakefile with the provided code (either in a block or a string).
+ # Create a new +Rakefile+ with the provided code (either in a block or a string).
#
# rakefile("bootstrap.rake") do
# project = ask("What is the UNIX name of your project?")
@@ -213,7 +213,7 @@ module Rails
in_root { run("#{extify(:capify)} .", verbose: false) }
end
- # Make an entry in Rails routing file config/routes.rb
+ # Make an entry in Rails routing file <tt>config/routes.rb</tt>
#
# route "root 'welcome#index'"
def route(routing_code)
diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb
index 2022b4ed3d..4988602aea 100644
--- a/railties/lib/rails/generators/app_base.rb
+++ b/railties/lib/rails/generators/app_base.rb
@@ -14,6 +14,7 @@ module Rails
DATABASES.concat(JDBC_DATABASES)
attr_accessor :rails_template
+ attr_accessor :app_template
add_shebang_option!
argument :app_path, type: :string
@@ -26,6 +27,9 @@ module Rails
class_option :template, type: :string, aliases: '-m',
desc: "Path to some #{name} template (can be a filesystem path or URL)"
+ class_option :app_template, type: :string, aliases: '-n',
+ desc: "Path to some #{name} template (can be a filesystem path or URL)"
+
class_option :skip_gemfile, type: :boolean, default: false,
desc: "Don't create a Gemfile"
@@ -47,6 +51,9 @@ module Rails
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 :database, type: :string, aliases: '-d', default: 'sqlite3',
desc: "Preconfigure for selected database (options: #{DATABASES.join('/')})"
@@ -109,6 +116,7 @@ module Rails
jbuilder_gemfile_entry,
sdoc_gemfile_entry,
platform_dependent_gemfile_entry,
+ spring_gemfile_entry,
@extra_entries].flatten.find_all(&@gem_filter)
end
@@ -118,6 +126,10 @@ module Rails
}.curry[@gem_filter]
end
+ def remove_gem(name)
+ add_gem_entry_filter { |gem| gem.name != name }
+ end
+
def builder
@builder ||= begin
builder_class = get_builder_class
@@ -158,6 +170,10 @@ module Rails
@target.send :add_gem_entry_filter, *args, &block
end
+ def remove_gem(*args, &block)
+ @target.send :remove_gem, *args, &block
+ end
+
def method_missing(name, *args, &block)
@commands << [name, args, block]
end
@@ -176,7 +192,8 @@ module Rails
def apply_rails_template
@recorder = TemplateRecorder.new self
- apply(rails_template, target: @recorder) if rails_template
+ apply(rails_template, target: self) if rails_template
+ apply(app_template, target: @recorder) if app_template
rescue Thor::Error, LoadError, Errno::ENOENT => e
raise Error, "The template [#{rails_template}] could not be loaded. Error: #{e}"
end
@@ -206,13 +223,18 @@ module Rails
def set_default_accessors!
self.destination_root = File.expand_path(app_path, destination_root)
- self.rails_template = case options[:template]
- when /^https?:\/\//
- options[:template]
- when String
- File.expand_path(options[:template], Dir.pwd)
- else
- options[:template]
+ self.rails_template = expand_template options[:template]
+ self.app_template = expand_template options[:app_template]
+ end
+
+ def expand_template(name)
+ case name
+ when /^https?:\/\//
+ name
+ when String
+ File.expand_path(name, Dir.pwd)
+ else
+ name
end
end
@@ -304,7 +326,7 @@ module Rails
'Use SCSS for stylesheets')
else
gems << GemfileEntry.version('sass-rails',
- '~> 4.0.0.rc1',
+ '~> 4.0.1',
'Use SCSS for stylesheets')
end
@@ -325,7 +347,7 @@ module Rails
def jbuilder_gemfile_entry
comment = 'Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder'
- GemfileEntry.version('jbuilder', '~> 1.2', comment)
+ GemfileEntry.version('jbuilder', '~> 2.0', comment)
end
def sdoc_gemfile_entry
@@ -365,6 +387,12 @@ module Rails
end
end
+ def spring_gemfile_entry
+ return [] unless spring_install?
+ comment = 'Spring speeds up development by keeping your application running in the background. Read more: https://github.com/jonleighton/spring'
+ GemfileEntry.new('spring', nil, comment, group: :development)
+ end
+
def bundle_command(command)
say_status :run, "bundle #{command}"
@@ -388,8 +416,22 @@ module Rails
end
end
+ def bundle_install?
+ !(options[:skip_gemfile] || options[:skip_bundle] || options[:pretend])
+ end
+
+ def spring_install?
+ !options[:skip_spring] && Process.respond_to?(:fork)
+ end
+
def run_bundle
- bundle_command('install') unless options[:skip_gemfile] || options[:skip_bundle] || options[:pretend]
+ bundle_command('install') if bundle_install?
+ end
+
+ def generate_spring_binstubs
+ if bundle_install? && spring_install?
+ bundle_command("exec spring binstub --all")
+ end
end
def empty_directory_with_keep_file(destination, config = {})
diff --git a/railties/lib/rails/generators/base.rb b/railties/lib/rails/generators/base.rb
index cf33b13fd8..67bab96a22 100644
--- a/railties/lib/rails/generators/base.rb
+++ b/railties/lib/rails/generators/base.rb
@@ -296,7 +296,7 @@ module Rails
end
end
- # Return the default value for the option name given doing a lookup in
+ # Returns the default value for the option name given doing a lookup in
# Rails::Generators.options.
def self.default_value_for_option(name, options)
default_for_option(Rails::Generators.options, name, options, options[:default])
diff --git a/railties/lib/rails/generators/erb.rb b/railties/lib/rails/generators/erb.rb
index 73e986ee7f..cfd77097d5 100644
--- a/railties/lib/rails/generators/erb.rb
+++ b/railties/lib/rails/generators/erb.rb
@@ -5,6 +5,10 @@ module Erb # :nodoc:
class Base < Rails::Generators::NamedBase #:nodoc:
protected
+ def formats
+ format
+ end
+
def format
:html
end
@@ -13,7 +17,7 @@ module Erb # :nodoc:
:erb
end
- def filename_with_extensions(name)
+ def filename_with_extensions(name, format)
[name, format, handler].compact.join(".")
end
end
diff --git a/railties/lib/rails/generators/erb/controller/controller_generator.rb b/railties/lib/rails/generators/erb/controller/controller_generator.rb
index 5f06734ab8..e62aece7c5 100644
--- a/railties/lib/rails/generators/erb/controller/controller_generator.rb
+++ b/railties/lib/rails/generators/erb/controller/controller_generator.rb
@@ -11,8 +11,10 @@ module Erb # :nodoc:
actions.each do |action|
@action = action
- @path = File.join(base_path, filename_with_extensions(action))
- template filename_with_extensions(:view), @path
+ Array(formats).each do |format|
+ @path = File.join(base_path, filename_with_extensions(action, format))
+ template filename_with_extensions(:view, format), @path
+ end
end
end
end
diff --git a/railties/lib/rails/generators/erb/mailer/mailer_generator.rb b/railties/lib/rails/generators/erb/mailer/mailer_generator.rb
index 7bcac30dde..66b17bd10e 100644
--- a/railties/lib/rails/generators/erb/mailer/mailer_generator.rb
+++ b/railties/lib/rails/generators/erb/mailer/mailer_generator.rb
@@ -5,8 +5,8 @@ module Erb # :nodoc:
class MailerGenerator < ControllerGenerator # :nodoc:
protected
- def format
- :text
+ def formats
+ [:text, :html]
end
end
end
diff --git a/railties/lib/rails/generators/erb/mailer/templates/view.html.erb b/railties/lib/rails/generators/erb/mailer/templates/view.html.erb
new file mode 100644
index 0000000000..8bb7c2b768
--- /dev/null
+++ b/railties/lib/rails/generators/erb/mailer/templates/view.html.erb
@@ -0,0 +1,5 @@
+<h1><%= class_name %>#<%= @action %></h1>
+
+<p>
+ <%%= @greeting %>, find me in app/views/<%= @path %>
+</p>
diff --git a/railties/lib/rails/generators/erb/scaffold/scaffold_generator.rb b/railties/lib/rails/generators/erb/scaffold/scaffold_generator.rb
index bacbc2d280..b219f459ac 100644
--- a/railties/lib/rails/generators/erb/scaffold/scaffold_generator.rb
+++ b/railties/lib/rails/generators/erb/scaffold/scaffold_generator.rb
@@ -14,8 +14,10 @@ module Erb # :nodoc:
def copy_view_files
available_views.each do |view|
- filename = filename_with_extensions(view)
- template filename, File.join("app/views", controller_file_path, filename)
+ Array(formats).each do |format|
+ filename = filename_with_extensions(view, format)
+ template filename, File.join("app/views", controller_file_path, filename)
+ end
end
end
diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb
index a2023886cd..d2eca5b2fb 100644
--- a/railties/lib/rails/generators/rails/app/app_generator.rb
+++ b/railties/lib/rails/generators/rails/app/app_generator.rb
@@ -78,6 +78,7 @@ module Rails
template "routes.rb"
template "application.rb"
template "environment.rb"
+ template "secrets.yml"
directory "environments"
directory "initializers"
@@ -225,18 +226,19 @@ module Rails
build(:vendor)
end
- def finish_template
- build(:leftovers)
- end
-
def delete_js_folder_skipping_javascript
if options[:skip_javascript]
remove_dir 'app/assets/javascripts'
end
end
+ def finish_template
+ build(:leftovers)
+ end
+
public_task :run_bundle
public_task :replay_template
+ public_task :generate_spring_binstubs
protected
diff --git a/railties/lib/rails/generators/rails/app/templates/config/application.rb b/railties/lib/rails/generators/rails/app/templates/config/application.rb
index ac41a0cadb..16fe50bab8 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/application.rb
+++ b/railties/lib/rails/generators/rails/app/templates/config/application.rb
@@ -15,7 +15,7 @@ require "action_mailer/railtie"
# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
-Bundler.require(:default, Rails.env)
+Bundler.require(*Rails.groups)
module <%= app_const_base %>
class Application < Rails::Application
@@ -30,10 +30,5 @@ module <%= app_const_base %>
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
# config.i18n.default_locale = :de
-<% if options.skip_sprockets? -%>
-
- # Disable the asset pipeline.
- config.assets.enabled = false
-<% end -%>
end
end
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
index c6dfd50d40..138e3a8664 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
@@ -23,6 +23,7 @@ test:
<<: *default
database: <%= app_name %>_test
+# Do not keep production credentials in the repository,
+# instead read the configuration from the environment.
production:
- <<: *default
- database: <%= app_name %>_production
+ url: <%%= ENV["DATABASE_URL"] %>
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
index fe53cd0ea2..2cdb592eeb 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
@@ -61,6 +61,7 @@ test:
<<: *default
database: <%= app_name[0,4] %>_tst
+# Do not keep production credentials in the repository,
+# instead read the configuration from the environment.
production:
- <<: *default
- database: <%= app_name[0,8] %>
+ url: <%%= ENV["DATABASE_URL"] %>
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
index be1dae332f..cefd30d519 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
@@ -53,6 +53,7 @@ test:
<<: *default
url: jdbc:db://localhost/<%= app_name %>_test
+# Do not keep production credentials in the repository,
+# instead read the configuration from the environment.
production:
- <<: *default
- url: jdbc:db://localhost/<%= app_name %>_production
+ url: <%%= ENV["DATABASE_URL"] %>
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
index 26e2a5976c..d31761349c 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
@@ -26,6 +26,6 @@ test:
<<: *default
database: <%= app_name %>_test
-production:
- <<: *default
- database: <%= app_name %>_production
+# Do not keep production credentials in the repository,
+# instead read the configuration from the environment.
+production: <%%= ENV["DATABASE_URL"] %>
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
index ccd44cf54b..0d248dc197 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
@@ -6,13 +6,20 @@
default: &default
adapter: postgresql
encoding: unicode
- username: <%= app_name %>
- password:
development:
<<: *default
database: <%= app_name %>_development
+ # The specified database role being used to connect to postgres.
+ # To create additional roles in postgres see `$ createuser --help`.
+ # When left blank, postgres will use the default role. This is
+ # the same name as the operating system user that initialized the database.
+ #username: <%= app_name %>
+
+ # The password associated with the postgres role (username).
+ #password:
+
# Connect on a TCP socket. Omitted by default since the client uses a
# domain socket that doesn't need configuration. Windows does not have
# domain sockets, so uncomment these lines.
@@ -35,6 +42,7 @@ test:
<<: *default
database: <%= app_name %>_test
+# Do not keep production credentials in the repository,
+# instead read the configuration from the environment.
production:
- <<: *default
- database: <%= app_name %>_production
+ url: <%%= ENV["DATABASE_URL"] %>
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
index 28c36eb82f..66eba3bf0d 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
@@ -18,6 +18,7 @@ test:
<<: *default
database: db/test.sqlite3
+# Do not keep production credentials in the repository,
+# instead read the configuration from the environment.
production:
- <<: *default
- database: db/production.sqlite3
+ url: <%%= ENV["DATABASE_URL"] %>
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
index 3fc7ce28a1..d618fc28a6 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
@@ -1,4 +1,4 @@
-# MySQL. Versions 4.1 and 5.0 are recommended.
+# MySQL. Versions 5.0+ are recommended.
#
# Install the MYSQL driver
# gem install mysql2
@@ -32,6 +32,11 @@ test:
<<: *default
database: <%= app_name %>_test
+# Avoid production credentials in the repository,
+# instead read the configuration from the environment.
+#
+# Example:
+# mysql2://myuser:mypass@localhost/somedatabase
+#
production:
- <<: *default
- database: <%= app_name %>_production
+ url: <%%= ENV["DATABASE_URL"] %>
diff --git a/railties/lib/rails/generators/rails/app/templates/config/databases/oracle.yml b/railties/lib/rails/generators/rails/app/templates/config/databases/oracle.yml
index d5b52c969b..d469ec0f99 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
@@ -32,6 +32,7 @@ test:
<<: *default
database: <%= app_name %>_test
+# Do not keep production credentials in the repository,
+# instead read the configuration from the environment.
production:
- <<: *default
- database: <%= app_name %>_production
+ url: <%%= ENV["DATABASE_URL"] %>
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
index eaeb82bddd..93f48656b2 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
@@ -17,16 +17,23 @@
default: &default
adapter: postgresql
encoding: unicode
- # For details on connection pooling, see rails configration guide
+ # For details on connection pooling, see rails configuration guide
# http://guides.rubyonrails.org/configuring.html#database-pooling
pool: 5
- username: <%= app_name %>
- password:
development:
<<: *default
database: <%= app_name %>_development
+ # The specified database role being used to connect to postgres.
+ # To create additional roles in postgres see `$ createuser --help`.
+ # When left blank, postgres will use the default role. This is
+ # the same name as the operating system user that initialized the database.
+ #username: <%= app_name %>
+
+ # The password associated with the postgres role (username).
+ #password:
+
# Connect on a TCP socket. Omitted by default since the client uses a
# domain socket that doesn't need configuration. Windows does not have
# domain sockets, so uncomment these lines.
@@ -52,6 +59,11 @@ test:
<<: *default
database: <%= app_name %>_test
+# Do not keep production credentials in the repository,
+# instead read the configuration from the environment.
+#
+# Example:
+# postgres://myuser:mypass@localhost/somedatabase
+#
production:
- <<: *default
- database: <%= app_name %>_production
+ url: <%%= ENV["DATABASE_URL"] %>
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
index 1c1a37ca8d..7312ddb6cd 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
@@ -20,6 +20,11 @@ test:
<<: *default
database: db/test.sqlite3
+# Do not keep production credentials in the repository,
+# instead read the configuration from the environment.
+#
+# Example:
+# sqlite3://myuser:mypass@localhost/full/path/to/somedatabase
+#
production:
- <<: *default
- database: db/production.sqlite3
+ url: <%%= ENV["DATABASE_URL"] %>
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
index 4855f66c0d..aa960e493e 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
@@ -42,6 +42,7 @@ test:
<<: *default
database: <%= app_name %>_test
+# Do not keep production credentials in the repository,
+# instead read the configuration from the environment.
production:
- <<: *default
- database: <%= app_name %>_production
+ url: <%%= ENV["DATABASE_URL"] %>
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 b724d468a2..cce4743a33 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
@@ -29,5 +29,10 @@ Rails.application.configure do
# This option may cause significant delays in view rendering with a large
# number of complex assets.
config.assets.debug = true
+
+ # Adds additional error checking when serving assets at runtime.
+ # Checks for improperly declared sprockets dependencies.
+ # Raises helpful error messages.
+ config.assets.raise_runtime_errors = true
<%- end -%>
end
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 1dfc9f136b..3baa382bd6 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
@@ -70,7 +70,7 @@ Rails.application.configure do
# config.action_mailer.raise_delivery_errors = false
# Enable locale fallbacks for I18n (makes lookups for any locale fall back to
- # the I18n.default_locale when a translation can not be found).
+ # the I18n.default_locale when a translation cannot be found).
config.i18n.fallbacks = true
# Send deprecation notices to registered listeners.
diff --git a/railties/lib/rails/generators/rails/app/templates/config/initializers/secret_token.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/secrets.yml
index f3cc6098a3..6e2c45e119 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/initializers/secret_token.rb.tt
+++ b/railties/lib/rails/generators/rails/app/templates/config/secrets.yml
@@ -7,6 +7,16 @@
# no regular words or you'll be exposed to dictionary attacks.
# You can use `rake secret` to generate a secure secret key.
-# Make sure your secret_key_base is kept private
+# Make sure the secrets in this file are kept private
# if you're sharing your code publicly.
-Rails.application.config.secret_key_base = '<%= app_secret %>'
+
+development:
+ secret_key_base: <%= app_secret %>
+
+test:
+ secret_key_base: <%= app_secret %>
+
+# Do not keep production secrets in the repository,
+# instead read values from the environment.
+production:
+ secret_key_base: <%%= ENV["RAILS_SECRET_KEY_BASE"] %>
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
index 4fd060341e..4ade1a0bdc 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
@@ -4,8 +4,6 @@ require 'rails/test_help'
class ActiveSupport::TestCase
<% unless options[:skip_active_record] -%>
- ActiveRecord::Migration.check_pending!
-
# Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
#
# Note: You'll currently still have to declare fixtures explicitly in integration tests
diff --git a/railties/lib/rails/generators/rails/plugin/templates/Gemfile b/railties/lib/rails/generators/rails/plugin/templates/Gemfile
index d576784415..88ec4e6354 100644
--- a/railties/lib/rails/generators/rails/plugin/templates/Gemfile
+++ b/railties/lib/rails/generators/rails/plugin/templates/Gemfile
@@ -39,5 +39,7 @@ end
<% end -%>
<% end -%>
+<% unless defined?(JRUBY_VERSION) -%>
# To use debugger
# gem 'debugger'
+<% end -%>
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 a0e5553e44..e4a2bc2b0f 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
@@ -9,7 +9,7 @@ module Rails
# should give you
#
# namespace :admin do
- # namespace :users
+ # namespace :users do
# resources :products
# end
# end
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 3334b189bf..85dee1a066 100644
--- a/railties/lib/rails/generators/test_unit/mailer/mailer_generator.rb
+++ b/railties/lib/rails/generators/test_unit/mailer/mailer_generator.rb
@@ -4,11 +4,18 @@ module TestUnit # :nodoc:
module Generators # :nodoc:
class MailerGenerator < Base # :nodoc:
argument :actions, type: :array, default: [], banner: "method method"
- check_class_collision suffix: "Test"
+
+ def check_class_collision
+ class_collisions "#{class_name}Test", "#{class_name}Preview"
+ end
def create_test_files
template "functional_test.rb", File.join('test/mailers', class_path, "#{file_name}_test.rb")
end
+
+ def create_preview_files
+ template "preview.rb", File.join('test/mailers/previews', class_path, "#{file_name}_preview.rb")
+ end
end
end
end
diff --git a/railties/lib/rails/generators/test_unit/mailer/templates/preview.rb b/railties/lib/rails/generators/test_unit/mailer/templates/preview.rb
new file mode 100644
index 0000000000..3bfd5426e8
--- /dev/null
+++ b/railties/lib/rails/generators/test_unit/mailer/templates/preview.rb
@@ -0,0 +1,13 @@
+<% module_namespacing do -%>
+# Preview all emails at http://localhost:3000/rails/mailers/<%= file_path %>
+class <%= class_name %>Preview < ActionMailer::Preview
+<% actions.each do |action| -%>
+
+ # Preview this email at http://localhost:3000/rails/mailers/<%= file_path %>/<%= action %>
+ def <%= action %>
+ <%= class_name %>.<%= action %>
+ end
+<% end -%>
+
+end
+<% end -%>
diff --git a/railties/lib/rails/generators/testing/behaviour.rb b/railties/lib/rails/generators/testing/behaviour.rb
index 7576eba6e0..8e9028a3fb 100644
--- a/railties/lib/rails/generators/testing/behaviour.rb
+++ b/railties/lib/rails/generators/testing/behaviour.rb
@@ -61,9 +61,11 @@ module Rails
# You can provide a configuration hash as second argument. This method returns the output
# printed by the generator.
def run_generator(args=self.default_arguments, config={})
- capture(:stdout) do
- args += ['--skip-bundle'] unless args.include? '--dev'
- self.generator_class.start(args, config.reverse_merge(destination_root: destination_root))
+ without_thor_debug do
+ capture(:stdout) do
+ args += ['--skip-bundle'] unless args.include? '--dev'
+ self.generator_class.start(args, config.reverse_merge(destination_root: destination_root))
+ end
end
end
@@ -100,6 +102,14 @@ module Rails
dirname, file_name = File.dirname(absolute), File.basename(absolute).sub(/\.rb$/, '')
Dir.glob("#{dirname}/[0-9]*_*.rb").grep(/\d+_#{file_name}.rb$/).first
end
+
+ # TODO: remove this once Bundler 1.5.2 is released
+ def without_thor_debug # :nodoc:
+ thor_debug, ENV['THOR_DEBUG'] = ENV['THOR_DEBUG'], nil
+ yield
+ ensure
+ ENV['THOR_DEBUG'] = thor_debug
+ end
end
end
end
diff --git a/railties/lib/rails/info_controller.rb b/railties/lib/rails/info_controller.rb
index 85ea11b4e7..908c4ce65e 100644
--- a/railties/lib/rails/info_controller.rb
+++ b/railties/lib/rails/info_controller.rb
@@ -1,9 +1,9 @@
+require 'rails/application_controller'
require 'action_dispatch/routing/inspector'
-class Rails::InfoController < ActionController::Base # :nodoc:
- self.view_paths = File.expand_path('../templates', __FILE__)
+class Rails::InfoController < Rails::ApplicationController # :nodoc:
prepend_view_path ActionDispatch::DebugExceptions::RESCUES_TEMPLATE_PATH
- layout -> { request.xhr? ? nil : 'application' }
+ layout -> { request.xhr? ? false : 'application' }
before_filter :require_local!
@@ -20,16 +20,4 @@ class Rails::InfoController < ActionController::Base # :nodoc:
@routes_inspector = ActionDispatch::Routing::RoutesInspector.new(_routes.routes)
@page_title = 'Routes'
end
-
- protected
-
- def require_local!
- unless local_request?
- render text: '<p>For security purposes, this information is only available to local requests.</p>', status: :forbidden
- end
- end
-
- def local_request?
- Rails.application.config.consider_all_requests_local || request.local?
- end
end
diff --git a/railties/lib/rails/mailers_controller.rb b/railties/lib/rails/mailers_controller.rb
new file mode 100644
index 0000000000..dd318f52e5
--- /dev/null
+++ b/railties/lib/rails/mailers_controller.rb
@@ -0,0 +1,73 @@
+require 'rails/application_controller'
+
+class Rails::MailersController < Rails::ApplicationController # :nodoc:
+ prepend_view_path ActionDispatch::DebugExceptions::RESCUES_TEMPLATE_PATH
+
+ before_filter :require_local!
+ before_filter :find_preview, only: :preview
+
+ def index
+ @previews = ActionMailer::Preview.all
+ @page_title = "Mailer Previews"
+ end
+
+ def preview
+ if params[:path] == @preview.preview_name
+ @page_title = "Mailer Previews for #{@preview.preview_name}"
+ render action: 'mailer'
+ else
+ email = File.basename(params[:path])
+
+ if @preview.email_exists?(email)
+ @email = @preview.call(email)
+
+ if params[:part]
+ part_type = Mime::Type.lookup(params[:part])
+
+ if part = find_part(part_type)
+ response.content_type = part_type
+ render text: part.respond_to?(:decoded) ? part.decoded : part
+ else
+ raise AbstractController::ActionNotFound, "Email part '#{part_type}' not found in #{@preview.name}##{email}"
+ end
+ else
+ @part = find_preferred_part(request.format, Mime::HTML, Mime::TEXT)
+ render action: 'email', layout: false, formats: %w[html]
+ end
+ else
+ raise AbstractController::ActionNotFound, "Email '#{email}' not found in #{@preview.name}"
+ end
+ end
+ end
+
+ protected
+ def find_preview
+ candidates = []
+ params[:path].to_s.scan(%r{/|$}){ candidates << $` }
+ preview = candidates.detect{ |candidate| ActionMailer::Preview.exists?(candidate) }
+
+ if preview
+ @preview = ActionMailer::Preview.find(preview)
+ else
+ raise AbstractController::ActionNotFound, "Mailer preview '#{params[:path]}' not found"
+ end
+ end
+
+ def find_preferred_part(*formats)
+ if @email.multipart?
+ formats.each do |format|
+ return find_part(format) if @email.parts.any?{ |p| p.mime_type == format }
+ end
+ else
+ @email
+ end
+ end
+
+ def find_part(format)
+ if @email.multipart?
+ @email.parts.find{ |p| p.mime_type == format }
+ elsif @email.mime_type == format
+ @email
+ end
+ end
+end \ No newline at end of file
diff --git a/railties/lib/rails/paths.rb b/railties/lib/rails/paths.rb
index f512aefb23..117bb37487 100644
--- a/railties/lib/rails/paths.rb
+++ b/railties/lib/rails/paths.rb
@@ -24,7 +24,7 @@ module Rails
#
# Notice that when you add a path using +add+, the path object created already
# contains the path with the same path value given to +add+. In some situations,
- # you may not want this behavior, so you can give :with as option.
+ # you may not want this behavior, so you can give <tt>:with</tt> as option.
#
# root.add "config/routes", with: "config/routes.rb"
# root["config/routes"].inspect # => ["config/routes.rb"]
diff --git a/railties/lib/rails/railtie.rb b/railties/lib/rails/railtie.rb
index 89ca8cbe11..c63e0c0758 100644
--- a/railties/lib/rails/railtie.rb
+++ b/railties/lib/rails/railtie.rb
@@ -22,7 +22,7 @@ module Rails
#
# * creating initializers
# * configuring a Rails framework for the application, like setting a generator
- # * +adding config.*+ keys to the environment
+ # * adding <tt>config.*</tt> keys to the environment
# * setting up a subscriber with ActiveSupport::Notifications
# * adding rake tasks
#
@@ -63,8 +63,8 @@ module Rails
# end
# end
#
- # Finally, you can also pass :before and :after as option to initializer, in case
- # you want to couple it with a specific step in the initialization process.
+ # Finally, you can also pass <tt>:before</tt> and <tt>:after</tt> as option to initializer,
+ # in case you want to couple it with a specific step in the initialization process.
#
# == Configuration
#
diff --git a/railties/lib/rails/templates/layouts/application.html.erb b/railties/lib/rails/templates/layouts/application.html.erb
index 50a4755e45..5aecaa712a 100644
--- a/railties/lib/rails/templates/layouts/application.html.erb
+++ b/railties/lib/rails/templates/layouts/application.html.erb
@@ -29,7 +29,7 @@
</style>
</head>
<body>
-<h2>Your App: <%= link_to 'properties', '/rails/info/properties' %> | <%= link_to 'routes', '/rails/info/routes' %></h2>
+
<%= yield %>
</body>
diff --git a/railties/lib/rails/templates/rails/mailers/email.html.erb b/railties/lib/rails/templates/rails/mailers/email.html.erb
new file mode 100644
index 0000000000..977feb922b
--- /dev/null
+++ b/railties/lib/rails/templates/rails/mailers/email.html.erb
@@ -0,0 +1,98 @@
+<!DOCTYPE html>
+<html><head>
+<meta name="viewport" content="width=device-width" />
+<style type="text/css">
+ header {
+ width: 100%;
+ padding: 10px 0 0 0;
+ margin: 0;
+ background: white;
+ font: 12px "Lucida Grande", sans-serif;
+ border-bottom: 1px solid #dedede;
+ overflow: hidden;
+ }
+
+ dl {
+ margin: 0 0 10px 0;
+ padding: 0;
+ }
+
+ dt {
+ width: 80px;
+ padding: 1px;
+ float: left;
+ clear: left;
+ text-align: right;
+ color: #7f7f7f;
+ }
+
+ dd {
+ margin-left: 90px; /* 80px + 10px */
+ padding: 1px;
+ }
+
+ iframe {
+ border: 0;
+ width: 100%;
+ height: 800px;
+ }
+</style>
+</head>
+
+<body>
+<header>
+ <dl>
+ <% if @email.respond_to?(:smtp_envelope_from) && Array(@email.from) != Array(@email.smtp_envelope_from) %>
+ <dt>SMTP-From:</dt>
+ <dd><%= @email.smtp_envelope_from %></dd>
+ <% end %>
+
+ <% if @email.respond_to?(:smtp_envelope_to) && @email.to != @email.smtp_envelope_to %>
+ <dt>SMTP-To:</dt>
+ <dd><%= @email.smtp_envelope_to %></dd>
+ <% end %>
+
+ <dt>From:</dt>
+ <dd><%= @email.header['from'] %></dd>
+
+ <% if @email.reply_to %>
+ <dt>Reply-To:</dt>
+ <dd><%= @email.header['reply-to'] %></dd>
+ <% end %>
+
+ <dt>To:</dt>
+ <dd><%= @email.header['to'] %></dd>
+
+ <% if @email.cc %>
+ <dt>CC:</dt>
+ <dd><%= @email.header['cc'] %></dd>
+ <% end %>
+
+ <dt>Date:</dt>
+ <dd><%= Time.current.rfc2822 %></dd>
+
+ <dt>Subject:</dt>
+ <dd><strong><%= @email.subject %></strong></dd>
+
+ <% unless @email.attachments.nil? || @email.attachments.empty? %>
+ <dt>Attachments:</dt>
+ <dd>
+ <%= @email.attachments.map { |a| a.respond_to?(:original_filename) ? a.original_filename : a.filename }.inspect %>
+ </dd>
+ <% end %>
+
+ <% if @email.multipart? %>
+ <dd>
+ <select onchange="document.getElementsByName('messageBody')[0].src=this.options[this.selectedIndex].value;">
+ <option <%= request.format == Mime::HTML ? 'selected' : '' %> value="?part=text%2Fhtml">View as HTML email</option>
+ <option <%= request.format == Mime::TEXT ? 'selected' : '' %> value="?part=text%2Fplain">View as plain-text email</option>
+ </select>
+ </dd>
+ <% end %>
+ </dl>
+</header>
+
+<iframe seamless name="messageBody" src="?part=<%= Rack::Utils.escape(@part.mime_type) %>"></iframe>
+
+</body>
+</html> \ No newline at end of file
diff --git a/railties/lib/rails/templates/rails/mailers/index.html.erb b/railties/lib/rails/templates/rails/mailers/index.html.erb
new file mode 100644
index 0000000000..c4c9757d57
--- /dev/null
+++ b/railties/lib/rails/templates/rails/mailers/index.html.erb
@@ -0,0 +1,8 @@
+<% @previews.each do |preview| %>
+<h3><%= link_to preview.preview_name.titleize, "/rails/mailers/#{preview.preview_name}" %></h3>
+<ul>
+<% preview.emails.each do |email| %>
+<li><%= link_to email, "/rails/mailers/#{preview.preview_name}/#{email}" %></li>
+<% end %>
+</ul>
+<% end %>
diff --git a/railties/lib/rails/templates/rails/mailers/mailer.html.erb b/railties/lib/rails/templates/rails/mailers/mailer.html.erb
new file mode 100644
index 0000000000..607c8d1677
--- /dev/null
+++ b/railties/lib/rails/templates/rails/mailers/mailer.html.erb
@@ -0,0 +1,6 @@
+<h3><%= @preview.preview_name.titleize %></h3>
+<ul>
+<% @preview.emails.each do |email| %>
+<li><%= link_to email, "/rails/mailers/#{@preview.preview_name}/#{email}" %></li>
+<% end %>
+</ul>
diff --git a/railties/lib/rails/test_help.rb b/railties/lib/rails/test_help.rb
index be801befc2..2e6356343d 100644
--- a/railties/lib/rails/test_help.rb
+++ b/railties/lib/rails/test_help.rb
@@ -11,10 +11,12 @@ require 'rails/generators/test_case'
# Config Rails backtrace in tests.
require 'rails/backtrace_cleaner'
if ENV["BACKTRACE"].nil?
- MiniTest.backtrace_filter = Rails.backtrace_cleaner
+ Minitest.backtrace_filter = Rails.backtrace_cleaner
end
if defined?(ActiveRecord::Base)
+ ActiveRecord::Migration.maintain_test_schema!
+
class ActiveSupport::TestCase
include ActiveRecord::TestFixtures
self.fixture_path = "#{Rails.root}/test/fixtures/"
diff --git a/railties/lib/rails/test_unit/testing.rake b/railties/lib/rails/test_unit/testing.rake
index 38107e77b2..285e2ce846 100644
--- a/railties/lib/rails/test_unit/testing.rake
+++ b/railties/lib/rails/test_unit/testing.rake
@@ -1,4 +1,3 @@
-require 'rbconfig'
require 'rake/testtask'
require 'rails/test_unit/sub_test_task'
diff --git a/railties/lib/rails/version.rb b/railties/lib/rails/version.rb
index 5a6d8d0983..923cab4e2a 100644
--- a/railties/lib/rails/version.rb
+++ b/railties/lib/rails/version.rb
@@ -3,7 +3,7 @@ module Rails
MAJOR = 4
MINOR = 1
TINY = 0
- PRE = "beta"
+ PRE = "beta1"
STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
end
diff --git a/railties/lib/rails/welcome_controller.rb b/railties/lib/rails/welcome_controller.rb
index 45b764fa6b..de9cd18b01 100644
--- a/railties/lib/rails/welcome_controller.rb
+++ b/railties/lib/rails/welcome_controller.rb
@@ -1,6 +1,7 @@
-class Rails::WelcomeController < ActionController::Base # :nodoc:
- self.view_paths = File.expand_path('../templates', __FILE__)
- layout nil
+require 'rails/application_controller'
+
+class Rails::WelcomeController < Rails::ApplicationController # :nodoc:
+ layout false
def index
end
diff --git a/railties/test/abstract_unit.rb b/railties/test/abstract_unit.rb
index 643cc6b0ee..ade08d3f5a 100644
--- a/railties/test/abstract_unit.rb
+++ b/railties/test/abstract_unit.rb
@@ -14,6 +14,6 @@ require 'rails/all'
module TestApp
class Application < Rails::Application
config.root = File.dirname(__FILE__)
- config.secret_key_base = 'b3c631c314c0bbca50c1b2843150fe33'
+ secrets.secret_key_base = 'b3c631c314c0bbca50c1b2843150fe33'
end
end
diff --git a/railties/test/application/configuration_test.rb b/railties/test/application/configuration_test.rb
index 03a735b1c1..6158c416d7 100644
--- a/railties/test/application/configuration_test.rb
+++ b/railties/test/application/configuration_test.rb
@@ -250,7 +250,7 @@ module ApplicationTests
test "Use key_generator when secret_key_base is set" do
make_basic_app do |app|
- app.config.secret_key_base = 'b3c631c314c0bbca50c1b2843150fe33'
+ app.secrets.secret_key_base = 'b3c631c314c0bbca50c1b2843150fe33'
app.config.session_store :disabled
end
@@ -268,6 +268,74 @@ module ApplicationTests
assert_equal 'some_value', verifier.verify(last_response.body)
end
+ test "application verifier can be used in the entire application" do
+ make_basic_app do |app|
+ app.secrets.secret_key_base = 'b3c631c314c0bbca50c1b2843150fe33'
+ app.config.session_store :disabled
+ end
+
+ message = app.message_verifier(:sensitive_value).generate("some_value")
+
+ assert_equal 'some_value', Rails.application.message_verifier(:sensitive_value).verify(message)
+
+ secret = app.key_generator.generate_key('sensitive_value')
+ verifier = ActiveSupport::MessageVerifier.new(secret)
+ assert_equal 'some_value', verifier.verify(message)
+ end
+
+ test "application verifier can build different verifiers" do
+ make_basic_app do |app|
+ app.secrets.secret_key_base = 'b3c631c314c0bbca50c1b2843150fe33'
+ app.config.session_store :disabled
+ end
+
+ default_verifier = app.message_verifier(:sensitive_value)
+ text_verifier = app.message_verifier(:text)
+
+ message = text_verifier.generate('some_value')
+
+ assert_equal 'some_value', text_verifier.verify(message)
+ assert_raises ActiveSupport::MessageVerifier::InvalidSignature do
+ default_verifier.verify(message)
+ end
+
+ assert_equal default_verifier.object_id, app.message_verifier(:sensitive_value).object_id
+ assert_not_equal default_verifier.object_id, text_verifier.object_id
+ end
+
+ test "secrets.secret_key_base is used when config/secrets.yml is present" do
+ app_file 'config/secrets.yml', <<-YAML
+ development:
+ secret_key_base: 3b7cd727ee24e8444053437c36cc66c3
+ YAML
+
+ require "#{app_path}/config/environment"
+ assert_equal '3b7cd727ee24e8444053437c36cc66c3', app.secrets.secret_key_base
+ end
+
+ test "secret_key_base is copied from config to secrets when not set" do
+ remove_file "config/secrets.yml"
+ app_file 'config/initializers/secret_token.rb', <<-RUBY
+ Rails.application.config.secret_key_base = "3b7cd727ee24e8444053437c36cc66c3"
+ RUBY
+
+ require "#{app_path}/config/environment"
+ assert_equal '3b7cd727ee24e8444053437c36cc66c3', app.secrets.secret_key_base
+ end
+
+ test "custom secrets saved in config/secrets.yml are loaded in app secrets" do
+ app_file 'config/secrets.yml', <<-YAML
+ development:
+ secret_key_base: 3b7cd727ee24e8444053437c36cc66c3
+ aws_access_key_id: myamazonaccesskeyid
+ aws_secret_access_key: myamazonsecretaccesskey
+ YAML
+
+ require "#{app_path}/config/environment"
+ assert_equal 'myamazonaccesskeyid', app.secrets.aws_access_key_id
+ assert_equal 'myamazonsecretaccesskey', app.secrets.aws_secret_access_key
+ end
+
test "protect from forgery is the default in a new app" do
make_basic_app
@@ -459,7 +527,7 @@ module ApplicationTests
require "#{app_path}/config/environment"
require 'action_view/base'
- assert ActionView::Resolver.caching?
+ assert_equal true, ActionView::Resolver.caching?
end
test "config.action_view.cache_template_loading without cache_classes default" do
@@ -467,7 +535,7 @@ module ApplicationTests
require "#{app_path}/config/environment"
require 'action_view/base'
- assert !ActionView::Resolver.caching?
+ assert_equal false, ActionView::Resolver.caching?
end
test "config.action_view.cache_template_loading = false" do
@@ -478,7 +546,7 @@ module ApplicationTests
require "#{app_path}/config/environment"
require 'action_view/base'
- assert !ActionView::Resolver.caching?
+ assert_equal false, ActionView::Resolver.caching?
end
test "config.action_view.cache_template_loading = true" do
@@ -489,7 +557,21 @@ module ApplicationTests
require "#{app_path}/config/environment"
require 'action_view/base'
- assert ActionView::Resolver.caching?
+ assert_equal true, ActionView::Resolver.caching?
+ end
+
+ test "config.action_view.cache_template_loading with cache_classes in an environment" do
+ build_app(initializers: true)
+ add_to_env_config "development", "config.cache_classes = false"
+
+ # These requires are to emulate an engine loading Action View before the application
+ require 'action_view'
+ require 'action_view/railtie'
+ require 'action_view/base'
+
+ require "#{app_path}/config/environment"
+
+ assert_equal false, ActionView::Resolver.caching?
end
test "config.action_dispatch.show_exceptions is sent in env" do
diff --git a/railties/test/application/initializers/frameworks_test.rb b/railties/test/application/initializers/frameworks_test.rb
index 83104acf3c..3601a58f67 100644
--- a/railties/test/application/initializers/frameworks_test.rb
+++ b/railties/test/application/initializers/frameworks_test.rb
@@ -216,7 +216,7 @@ module ApplicationTests
require "#{app_path}/config/environment"
orig_database_url = ENV.delete("DATABASE_URL")
orig_rails_env, Rails.env = Rails.env, 'development'
- database_url_db_name = "db/database_url_db.sqlite3"
+ database_url_db_name = File.join(app_path, "db/database_url_db.sqlite3")
ENV["DATABASE_URL"] = "sqlite3://:@localhost/#{database_url_db_name}"
ActiveRecord::Base.establish_connection
assert ActiveRecord::Base.connection
diff --git a/railties/test/application/initializers/i18n_test.rb b/railties/test/application/initializers/i18n_test.rb
index 97df073ec7..bc34897cdf 100644
--- a/railties/test/application/initializers/i18n_test.rb
+++ b/railties/test/application/initializers/i18n_test.rb
@@ -183,5 +183,50 @@ en:
load_app
assert_fallbacks ca: [:ca, :"es-ES", :es, :'en-US', :en]
end
+
+ test "config.i18n.enforce_available_locales is set to true by default and avoids I18n warnings" do
+ add_to_config <<-RUBY
+ config.i18n.default_locale = :it
+ RUBY
+
+ output = capture(:stderr) { load_app }
+ assert_no_match %r{deprecated.*enforce_available_locales}, output
+ assert_equal true, I18n.enforce_available_locales
+
+ assert_raise I18n::InvalidLocale do
+ I18n.locale = :es
+ end
+ end
+
+ test "disable config.i18n.enforce_available_locales" do
+ add_to_config <<-RUBY
+ config.i18n.enforce_available_locales = false
+ config.i18n.default_locale = :fr
+ RUBY
+
+ output = capture(:stderr) { load_app }
+ assert_no_match %r{deprecated.*enforce_available_locales}, output
+ assert_equal false, I18n.enforce_available_locales
+
+ assert_nothing_raised do
+ I18n.locale = :es
+ end
+ end
+
+ test "default config.i18n.enforce_available_locales does not override I18n.enforce_available_locales" do
+ I18n.enforce_available_locales = false
+
+ add_to_config <<-RUBY
+ config.i18n.default_locale = :fr
+ RUBY
+
+ output = capture(:stderr) { load_app }
+ assert_no_match %r{deprecated.*enforce_available_locales}, output
+ assert_equal false, I18n.enforce_available_locales
+
+ assert_nothing_raised do
+ I18n.locale = :es
+ end
+ end
end
end
diff --git a/railties/test/application/mailer_previews_test.rb b/railties/test/application/mailer_previews_test.rb
new file mode 100644
index 0000000000..c588fd7012
--- /dev/null
+++ b/railties/test/application/mailer_previews_test.rb
@@ -0,0 +1,428 @@
+require 'isolation/abstract_unit'
+require 'rack/test'
+module ApplicationTests
+ class MailerPreviewsTest < ActiveSupport::TestCase
+ include ActiveSupport::Testing::Isolation
+ include Rack::Test::Methods
+
+ def setup
+ build_app
+ boot_rails
+ end
+
+ def teardown
+ teardown_app
+ end
+
+ test "/rails/mailers is accessible in development" do
+ app("development")
+ get "/rails/mailers"
+ assert_equal 200, last_response.status
+ end
+
+ test "/rails/mailers is not accessible in production" do
+ app("production")
+ get "/rails/mailers"
+ assert_equal 404, last_response.status
+ end
+
+ test "mailer previews are loaded from the default preview_path" do
+ mailer 'notifier', <<-RUBY
+ class Notifier < ActionMailer::Base
+ default from: "from@example.com"
+
+ def foo
+ mail to: "to@example.org"
+ end
+ end
+ RUBY
+
+ text_template 'notifier/foo', <<-RUBY
+ Hello, World!
+ RUBY
+
+ mailer_preview 'notifier', <<-RUBY
+ class NotifierPreview < ActionMailer::Preview
+ def foo
+ Notifier.foo
+ end
+ end
+ RUBY
+
+ app('development')
+
+ get "/rails/mailers"
+ assert_match '<h3><a href="/rails/mailers/notifier">Notifier</a></h3>', last_response.body
+ assert_match '<li><a href="/rails/mailers/notifier/foo">foo</a></li>', last_response.body
+ end
+
+ test "mailer previews are loaded from a custom preview_path" do
+ add_to_config "config.action_mailer.preview_path = '#{app_path}/lib/mailer_previews'"
+
+ mailer 'notifier', <<-RUBY
+ class Notifier < ActionMailer::Base
+ default from: "from@example.com"
+
+ def foo
+ mail to: "to@example.org"
+ end
+ end
+ RUBY
+
+ text_template 'notifier/foo', <<-RUBY
+ Hello, World!
+ RUBY
+
+ app_file 'lib/mailer_previews/notifier_preview.rb', <<-RUBY
+ class NotifierPreview < ActionMailer::Preview
+ def foo
+ Notifier.foo
+ end
+ end
+ RUBY
+
+ app('development')
+
+ get "/rails/mailers"
+ assert_match '<h3><a href="/rails/mailers/notifier">Notifier</a></h3>', last_response.body
+ assert_match '<li><a href="/rails/mailers/notifier/foo">foo</a></li>', last_response.body
+ end
+
+ test "mailer previews are reloaded across requests" do
+ app('development')
+
+ get "/rails/mailers"
+ assert_no_match '<h3><a href="/rails/mailers/notifier">Notifier</a></h3>', last_response.body
+
+ mailer 'notifier', <<-RUBY
+ class Notifier < ActionMailer::Base
+ default from: "from@example.com"
+
+ def foo
+ mail to: "to@example.org"
+ end
+ end
+ RUBY
+
+ text_template 'notifier/foo', <<-RUBY
+ Hello, World!
+ RUBY
+
+ mailer_preview 'notifier', <<-RUBY
+ class NotifierPreview < ActionMailer::Preview
+ def foo
+ Notifier.foo
+ end
+ end
+ RUBY
+
+ get "/rails/mailers"
+ assert_match '<h3><a href="/rails/mailers/notifier">Notifier</a></h3>', last_response.body
+
+ remove_file 'test/mailers/previews/notifier_preview.rb'
+ sleep(1)
+
+ get "/rails/mailers"
+ assert_no_match '<h3><a href="/rails/mailers/notifier">Notifier</a></h3>', last_response.body
+ end
+
+ test "mailer preview actions are added and removed" do
+ mailer 'notifier', <<-RUBY
+ class Notifier < ActionMailer::Base
+ default from: "from@example.com"
+
+ def foo
+ mail to: "to@example.org"
+ end
+ end
+ RUBY
+
+ text_template 'notifier/foo', <<-RUBY
+ Hello, World!
+ RUBY
+
+ mailer_preview 'notifier', <<-RUBY
+ class NotifierPreview < ActionMailer::Preview
+ def foo
+ Notifier.foo
+ end
+ end
+ RUBY
+
+ app('development')
+
+ get "/rails/mailers"
+ assert_match '<h3><a href="/rails/mailers/notifier">Notifier</a></h3>', last_response.body
+ assert_match '<li><a href="/rails/mailers/notifier/foo">foo</a></li>', last_response.body
+ assert_no_match '<li><a href="/rails/mailers/notifier/bar">bar</a></li>', last_response.body
+
+ mailer 'notifier', <<-RUBY
+ class Notifier < ActionMailer::Base
+ default from: "from@example.com"
+
+ def foo
+ mail to: "to@example.org"
+ end
+
+ def bar
+ mail to: "to@example.net"
+ end
+ end
+ RUBY
+
+ text_template 'notifier/foo', <<-RUBY
+ Hello, World!
+ RUBY
+
+ text_template 'notifier/bar', <<-RUBY
+ Goodbye, World!
+ RUBY
+
+ mailer_preview 'notifier', <<-RUBY
+ class NotifierPreview < ActionMailer::Preview
+ def foo
+ Notifier.foo
+ end
+
+ def bar
+ Notifier.bar
+ end
+ end
+ RUBY
+
+ sleep(1)
+
+ get "/rails/mailers"
+ assert_match '<h3><a href="/rails/mailers/notifier">Notifier</a></h3>', last_response.body
+ assert_match '<li><a href="/rails/mailers/notifier/foo">foo</a></li>', last_response.body
+ assert_match '<li><a href="/rails/mailers/notifier/bar">bar</a></li>', last_response.body
+
+ mailer 'notifier', <<-RUBY
+ class Notifier < ActionMailer::Base
+ default from: "from@example.com"
+
+ def foo
+ mail to: "to@example.org"
+ end
+ end
+ RUBY
+
+ remove_file 'app/views/notifier/bar.text.erb'
+
+ mailer_preview 'notifier', <<-RUBY
+ class NotifierPreview < ActionMailer::Preview
+ def foo
+ Notifier.foo
+ end
+ end
+ RUBY
+
+ sleep(1)
+
+ get "/rails/mailers"
+ assert_match '<h3><a href="/rails/mailers/notifier">Notifier</a></h3>', last_response.body
+ assert_match '<li><a href="/rails/mailers/notifier/foo">foo</a></li>', last_response.body
+ assert_no_match '<li><a href="/rails/mailers/notifier/bar">bar</a></li>', last_response.body
+ end
+
+ test "mailer previews are reloaded from a custom preview_path" do
+ add_to_config "config.action_mailer.preview_path = '#{app_path}/lib/mailer_previews'"
+
+ app('development')
+
+ get "/rails/mailers"
+ assert_no_match '<h3><a href="/rails/mailers/notifier">Notifier</a></h3>', last_response.body
+
+ mailer 'notifier', <<-RUBY
+ class Notifier < ActionMailer::Base
+ default from: "from@example.com"
+
+ def foo
+ mail to: "to@example.org"
+ end
+ end
+ RUBY
+
+ text_template 'notifier/foo', <<-RUBY
+ Hello, World!
+ RUBY
+
+ app_file 'lib/mailer_previews/notifier_preview.rb', <<-RUBY
+ class NotifierPreview < ActionMailer::Preview
+ def foo
+ Notifier.foo
+ end
+ end
+ RUBY
+
+ get "/rails/mailers"
+ assert_match '<h3><a href="/rails/mailers/notifier">Notifier</a></h3>', last_response.body
+
+ remove_file 'lib/mailer_previews/notifier_preview.rb'
+ sleep(1)
+
+ get "/rails/mailers"
+ assert_no_match '<h3><a href="/rails/mailers/notifier">Notifier</a></h3>', last_response.body
+ end
+
+ test "mailer preview not found" do
+ app('development')
+ get "/rails/mailers/notifier"
+ assert last_response.not_found?
+ assert_match "Mailer preview &#39;notifier&#39; not found", last_response.body
+ end
+
+ test "mailer preview email not found" do
+ mailer 'notifier', <<-RUBY
+ class Notifier < ActionMailer::Base
+ default from: "from@example.com"
+
+ def foo
+ mail to: "to@example.org"
+ end
+ end
+ RUBY
+
+ text_template 'notifier/foo', <<-RUBY
+ Hello, World!
+ RUBY
+
+ mailer_preview 'notifier', <<-RUBY
+ class NotifierPreview < ActionMailer::Preview
+ def foo
+ Notifier.foo
+ end
+ end
+ RUBY
+
+ app('development')
+
+ get "/rails/mailers/notifier/bar"
+ assert last_response.not_found?
+ assert_match "Email &#39;bar&#39; not found in NotifierPreview", last_response.body
+ end
+
+ test "mailer preview email part not found" do
+ mailer 'notifier', <<-RUBY
+ class Notifier < ActionMailer::Base
+ default from: "from@example.com"
+
+ def foo
+ mail to: "to@example.org"
+ end
+ end
+ RUBY
+
+ text_template 'notifier/foo', <<-RUBY
+ Hello, World!
+ RUBY
+
+ mailer_preview 'notifier', <<-RUBY
+ class NotifierPreview < ActionMailer::Preview
+ def foo
+ Notifier.foo
+ end
+ end
+ RUBY
+
+ app('development')
+
+ get "/rails/mailers/notifier/foo?part=text%2Fhtml"
+ assert last_response.not_found?
+ assert_match "Email part &#39;text/html&#39; not found in NotifierPreview#foo", last_response.body
+ end
+
+ test "message header uses full display names" do
+ mailer 'notifier', <<-RUBY
+ class Notifier < ActionMailer::Base
+ default from: "Ruby on Rails <core@rubyonrails.org>"
+
+ def foo
+ mail to: "Andrew White <andyw@pixeltrix.co.uk>",
+ cc: "David Heinemeier Hansson <david@heinemeierhansson.com>"
+ end
+ end
+ RUBY
+
+ text_template 'notifier/foo', <<-RUBY
+ Hello, World!
+ RUBY
+
+ mailer_preview 'notifier', <<-RUBY
+ class NotifierPreview < ActionMailer::Preview
+ def foo
+ Notifier.foo
+ end
+ end
+ RUBY
+
+ app('development')
+
+ get "/rails/mailers/notifier/foo"
+ assert_equal 200, last_response.status
+ assert_match "Ruby on Rails &lt;core@rubyonrails.org&gt;", last_response.body
+ assert_match "Andrew White &lt;andyw@pixeltrix.co.uk&gt;", last_response.body
+ assert_match "David Heinemeier Hansson &lt;david@heinemeierhansson.com&gt;", last_response.body
+ end
+
+ test "part menu selects correct option" do
+ mailer 'notifier', <<-RUBY
+ class Notifier < ActionMailer::Base
+ default from: "from@example.com"
+
+ def foo
+ mail to: "to@example.org"
+ end
+ end
+ RUBY
+
+ html_template 'notifier/foo', <<-RUBY
+ <p>Hello, World!</p>
+ RUBY
+
+ text_template 'notifier/foo', <<-RUBY
+ Hello, World!
+ RUBY
+
+ mailer_preview 'notifier', <<-RUBY
+ class NotifierPreview < ActionMailer::Preview
+ def foo
+ Notifier.foo
+ end
+ end
+ RUBY
+
+ app('development')
+
+ get "/rails/mailers/notifier/foo.html"
+ assert_equal 200, last_response.status
+ assert_match '<option selected value="?part=text%2Fhtml">View as HTML email</option>', last_response.body
+
+ get "/rails/mailers/notifier/foo.txt"
+ assert_equal 200, last_response.status
+ assert_match '<option selected value="?part=text%2Fplain">View as plain-text email</option>', last_response.body
+ end
+
+ private
+ def build_app
+ super
+ app_file "config/routes.rb", "Rails.application.routes.draw do; end"
+ end
+
+ def mailer(name, contents)
+ app_file("app/mailers/#{name}.rb", contents)
+ end
+
+ def mailer_preview(name, contents)
+ app_file("test/mailers/previews/#{name}_preview.rb", contents)
+ end
+
+ def html_template(name, contents)
+ app_file("app/views/#{name}.html.erb", contents)
+ end
+
+ def text_template(name, contents)
+ app_file("app/views/#{name}.text.erb", contents)
+ end
+ end
+end
diff --git a/railties/test/application/middleware/session_test.rb b/railties/test/application/middleware/session_test.rb
index 14a56176f5..31a64c2f5a 100644
--- a/railties/test/application/middleware/session_test.rb
+++ b/railties/test/application/middleware/session_test.rb
@@ -318,7 +318,7 @@ module ApplicationTests
add_to_config <<-RUBY
config.secret_token = "3b7cd727ee24e8444053437c36cc66c4"
- config.secret_key_base = nil
+ secrets.secret_key_base = nil
RUBY
require "#{app_path}/config/environment"
diff --git a/railties/test/application/middleware_test.rb b/railties/test/application/middleware_test.rb
index 20d1d76d78..1557b90d27 100644
--- a/railties/test/application/middleware_test.rb
+++ b/railties/test/application/middleware_test.rb
@@ -61,7 +61,7 @@ module ApplicationTests
boot!
- assert_equal "Rack::Cache", middleware.first
+ assert middleware.include?("Rack::Cache")
end
test "ActiveRecord::Migration::CheckPending is present when active_record.migration_error is set to :page_load" do
diff --git a/railties/test/application/rake/dbs_test.rb b/railties/test/application/rake/dbs_test.rb
index 4d348c6b4b..35d9c31c1e 100644
--- a/railties/test/application/rake/dbs_test.rb
+++ b/railties/test/application/rake/dbs_test.rb
@@ -1,4 +1,5 @@
require "isolation/abstract_unit"
+require "active_support/core_ext/string/strip"
module ApplicationTests
module RakeTests
@@ -16,11 +17,11 @@ module ApplicationTests
end
def database_url_db_name
- "db/database_url_db.sqlite3"
+ File.join(app_path, "db/database_url_db.sqlite3")
end
def set_database_url
- ENV['DATABASE_URL'] = "sqlite3://:@localhost/#{database_url_db_name}"
+ ENV['DATABASE_URL'] = File.join("sqlite3://:@localhost", database_url_db_name)
# ensure it's using the DATABASE_URL
FileUtils.rm_rf("#{app_path}/config/database.yml")
end
@@ -60,7 +61,7 @@ module ApplicationTests
`rails generate model book title:string;
bundle exec rake db:migrate`
output = `bundle exec rake db:migrate:status`
- assert_match(/database:\s+\S+#{expected[:database]}/, output)
+ assert_match(%r{database:\s+\S*#{Regexp.escape(expected[:database])}}, output)
assert_match(/up\s+\d{14}\s+Create books/, output)
end
end
@@ -126,7 +127,7 @@ module ApplicationTests
bundle exec rake db:migrate db:structure:dump`
structure_dump = File.read("db/structure.sql")
assert_match(/CREATE TABLE \"books\"/, structure_dump)
- `bundle exec rake db:drop db:structure:load`
+ `bundle exec rake environment db:drop db:structure:load`
assert_match(/#{expected[:database]}/,
ActiveRecord::Base.connection_config[:database])
require "#{app_path}/app/models/book"
@@ -153,7 +154,7 @@ module ApplicationTests
`rails generate model book title:string;
bundle exec rake db:migrate db:structure:dump db:test:load_structure`
ActiveRecord::Base.configurations = Rails.application.config.database_configuration
- ActiveRecord::Base.establish_connection 'test'
+ ActiveRecord::Base.establish_connection :test
require "#{app_path}/app/models/book"
#if structure is not loaded correctly, exception would be raised
assert Book.count, 0
@@ -166,6 +167,15 @@ module ApplicationTests
require "#{app_path}/config/environment"
db_test_load_structure
end
+
+ test 'db:test deprecation' do
+ require "#{app_path}/config/environment"
+ Dir.chdir(app_path) do
+ output = `bundle exec rake db:migrate db:test:prepare 2>&1`
+ assert_equal "WARNING: db:test:prepare is deprecated. The Rails test helper now maintains " \
+ "your test schema automatically, see the release notes for details.\n", output
+ end
+ end
end
end
end
diff --git a/railties/test/application/rake_test.rb b/railties/test/application/rake_test.rb
index 08316d80e6..317e73245c 100644
--- a/railties/test/application/rake_test.rb
+++ b/railties/test/application/rake_test.rb
@@ -187,7 +187,7 @@ module ApplicationTests
def test_scaffold_tests_pass_by_default
output = Dir.chdir(app_path) do
`rails generate scaffold user username:string password:string;
- bundle exec rake db:migrate db:test:clone test`
+ bundle exec rake db:migrate test`
end
assert_match(/7 runs, 13 assertions, 0 failures, 0 errors/, output)
@@ -197,7 +197,7 @@ module ApplicationTests
def test_scaffold_with_references_columns_tests_pass_by_default
output = Dir.chdir(app_path) do
`rails generate scaffold LineItems product:references cart:belongs_to;
- bundle exec rake db:migrate db:test:clone test`
+ bundle exec rake db:migrate test`
end
assert_match(/7 runs, 13 assertions, 0 failures, 0 errors/, output)
@@ -208,7 +208,8 @@ module ApplicationTests
add_to_config "config.active_record.schema_format = :sql"
output = Dir.chdir(app_path) do
`rails generate scaffold user username:string;
- bundle exec rake db:migrate db:test:clone 2>&1 --trace`
+ bundle exec rake db:migrate;
+ bundle exec rake db:test:clone 2>&1 --trace`
end
assert_match(/Execute db:test:clone_structure/, output)
end
@@ -217,7 +218,8 @@ module ApplicationTests
add_to_config "config.active_record.schema_format = :sql"
output = Dir.chdir(app_path) do
`rails generate scaffold user username:string;
- bundle exec rake db:migrate db:test:prepare 2>&1 --trace`
+ bundle exec rake db:migrate;
+ bundle exec rake db:test:prepare 2>&1 --trace`
end
assert_match(/Execute db:test:load_structure/, output)
end
diff --git a/railties/test/application/test_test.rb b/railties/test/application/test_test.rb
index 6f2f328588..a223180169 100644
--- a/railties/test/application/test_test.rb
+++ b/railties/test/application/test_test.rb
@@ -67,10 +67,55 @@ module ApplicationTests
assert_match %r{/app/test/unit/failing_test\.rb}, output
end
+ test "migrations" do
+ output = script('generate model user name:string')
+ version = output.match(/(\d+)_create_users\.rb/)[1]
+
+ app_file 'test/models/user_test.rb', <<-RUBY
+ require 'test_helper'
+
+ class UserTest < ActiveSupport::TestCase
+ test "user" do
+ User.create! name: "Jon"
+ end
+ end
+ RUBY
+ app_file 'db/schema.rb', ''
+
+ assert_unsuccessful_run "models/user_test.rb", "Migrations are pending"
+
+ app_file 'db/schema.rb', <<-RUBY
+ ActiveRecord::Schema.define(version: #{version}) do
+ create_table :users do |t|
+ t.string :name
+ end
+ end
+ RUBY
+
+ app_file 'config/initializers/disable_maintain_test_schema.rb', <<-RUBY
+ Rails.application.config.active_record.maintain_test_schema = false
+ RUBY
+
+ assert_unsuccessful_run "models/user_test.rb", "Could not find table 'users'"
+
+ File.delete "#{app_path}/config/initializers/disable_maintain_test_schema.rb"
+
+ result = assert_successful_test_run('models/user_test.rb')
+ assert !result.include?("create_table(:users)")
+ end
+
private
+ def assert_unsuccessful_run(name, message)
+ result = run_test_file(name)
+ assert_not_equal 0, $?.to_i
+ assert result.include?(message)
+ result
+ end
+
def assert_successful_test_run(name)
result = run_test_file(name)
assert_equal 0, $?.to_i, result
+ result
end
def run_test_file(name, options = {})
@@ -83,7 +128,7 @@ module ApplicationTests
env["RUBYLIB"] = $:.join(':')
Dir.chdir(app_path) do
- `#{env_string(env)} #{Gem.ruby} #{args.join(' ')}`
+ `#{env_string(env)} #{Gem.ruby} #{args.join(' ')} 2>&1`
end
end
diff --git a/railties/test/commands/dbconsole_test.rb b/railties/test/commands/dbconsole_test.rb
index edb92b3aa2..24db395e6e 100644
--- a/railties/test/commands/dbconsole_test.rb
+++ b/railties/test/commands/dbconsole_test.rb
@@ -2,29 +2,74 @@ require 'abstract_unit'
require 'rails/commands/dbconsole'
class Rails::DBConsoleTest < ActiveSupport::TestCase
- def teardown
- %w[PGUSER PGHOST PGPORT PGPASSWORD].each{|key| ENV.delete(key)}
- end
- def test_config
- Rails::DBConsole.const_set(:APP_PATH, "erb")
-
- app_config({})
- capture_abort { Rails::DBConsole.new.config }
- assert aborted
- assert_match(/No database is configured for the environment '\w+'/, output)
- app_config(test: "with_init")
- assert_equal Rails::DBConsole.new.config, "with_init"
-
- app_db_file("test:\n without_init")
- assert_equal Rails::DBConsole.new.config, "without_init"
-
- app_db_file("test:\n <%= Rails.something_app_specific %>")
- assert_equal Rails::DBConsole.new.config, "with_init"
+ def setup
+ Rails::DBConsole.const_set('APP_PATH', 'rails/all')
+ end
- app_db_file("test:\n\ninvalid")
- assert_equal Rails::DBConsole.new.config, "with_init"
+ def teardown
+ Rails::DBConsole.send(:remove_const, 'APP_PATH')
+ %w[PGUSER PGHOST PGPORT PGPASSWORD DATABASE_URL].each{|key| ENV.delete(key)}
+ end
+
+ def test_config_with_db_config_only
+ config_sample = {
+ "test"=> {
+ "adapter"=> "sqlite3",
+ "host"=> "localhost",
+ "port"=> "9000",
+ "database"=> "foo_test",
+ "user"=> "foo",
+ "password"=> "bar",
+ "pool"=> "5",
+ "timeout"=> "3000"
+ }
+ }
+ app_db_config(config_sample)
+ assert_equal Rails::DBConsole.new.config, config_sample["test"]
+ end
+
+ def test_config_with_no_db_config
+ app_db_config(nil)
+ assert_raise(ActiveRecord::AdapterNotSpecified) {
+ Rails::DBConsole.new.config
+ }
+ end
+
+ def test_config_with_database_url_only
+ ENV['DATABASE_URL'] = 'postgresql://foo:bar@localhost:9000/foo_test?pool=5&timeout=3000'
+ app_db_config(nil)
+ expected = {
+ "adapter" => "postgresql",
+ "host" => "localhost",
+ "port" => 9000,
+ "database" => "foo_test",
+ "username" => "foo",
+ "password" => "bar",
+ "pool" => "5",
+ "timeout" => "3000"
+ }.sort
+ assert_equal expected, Rails::DBConsole.new.config.sort
+ end
+
+ def test_config_choose_database_url_if_exists
+ host = "database-url-host.com"
+ ENV['DATABASE_URL'] = "postgresql://foo:bar@#{host}:9000/foo_test?pool=5&timeout=3000"
+ sample_config = {
+ "test" => {
+ "adapter" => "postgresql",
+ "host" => "not-the-#{host}",
+ "port" => 9000,
+ "database" => "foo_test",
+ "username" => "foo",
+ "password" => "bar",
+ "pool" => "5",
+ "timeout" => "3000"
+ }
+ }
+ app_db_config(sample_config)
+ assert_equal host, Rails::DBConsole.new.config["host"]
end
def test_env
@@ -177,6 +222,10 @@ class Rails::DBConsoleTest < ActiveSupport::TestCase
private
+ def app_db_config(results)
+ Rails.application.config.stubs(:database_configuration).returns(results || {})
+ end
+
def dbconsole
@dbconsole ||= Rails::DBConsole.new(nil)
end
@@ -197,11 +246,4 @@ class Rails::DBConsoleTest < ActiveSupport::TestCase
end
end
- def app_db_file(result)
- IO.stubs(:read).with("config/database.yml").returns(result)
- end
-
- def app_config(result)
- Rails.application.config.stubs(:database_configuration).returns(result.stringify_keys)
- end
end
diff --git a/railties/test/configuration/middleware_stack_proxy_test.rb b/railties/test/configuration/middleware_stack_proxy_test.rb
index 2442cb995d..6f3e45f320 100644
--- a/railties/test/configuration/middleware_stack_proxy_test.rb
+++ b/railties/test/configuration/middleware_stack_proxy_test.rb
@@ -39,7 +39,7 @@ module Rails
@stack.swap :foo
@stack.delete :foo
- mock = MiniTest::Mock.new
+ mock = Minitest::Mock.new
mock.expect :send, nil, [:swap, :foo]
mock.expect :send, nil, [:delete, :foo]
@@ -50,7 +50,7 @@ module Rails
private
def assert_playback(msg_name, args)
- mock = MiniTest::Mock.new
+ mock = Minitest::Mock.new
mock.expect :send, nil, [msg_name, args]
@stack.merge_into(mock)
mock.verify
diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb
index f89ff66e3e..be109cc598 100644
--- a/railties/test/generators/app_generator_test.rb
+++ b/railties/test/generators/app_generator_test.rb
@@ -163,56 +163,71 @@ class AppGeneratorTest < Rails::Generators::TestCase
end
end
- def test_add_gemfile_entry
- template = Tempfile.open 'my_template'
- template.puts 'gemfile_entry "tenderlove"'
- template.flush
+ def test_arbitrary_code
+ output = Tempfile.open('my_template') do |template|
+ template.puts 'puts "You are using Rails version #{Rails::VERSION::STRING}."'
+ template.close
+ run_generator([destination_root, "-m", template.path])
+ end
+ assert_match 'You are using', output
+ end
- run_generator([destination_root, "-m", template.path])
- assert_file "Gemfile", /tenderlove/
- ensure
- template.close
- template.unlink
+ def test_add_gemfile_entry
+ Tempfile.open('my_template') do |template|
+ template.puts 'gemfile_entry "tenderlove"'
+ template.flush
+ template.close
+ run_generator([destination_root, "-n", template.path])
+ assert_file "Gemfile", /tenderlove/
+ end
end
def test_add_skip_entry
- template = Tempfile.open 'my_template'
- template.puts 'add_gem_entry_filter { |gem| gem.name != "jbuilder" }'
- template.flush
+ Tempfile.open 'my_template' do |template|
+ template.puts 'add_gem_entry_filter { |gem| gem.name != "jbuilder" }'
+ template.close
- run_generator([destination_root, "-m", template.path])
- assert_file "Gemfile" do |contents|
- assert_no_match 'jbuilder', contents
+ run_generator([destination_root, "-n", template.path])
+ assert_file "Gemfile" do |contents|
+ assert_no_match 'jbuilder', contents
+ end
end
- ensure
- template.close
- template.unlink
end
- def test_skip_turbolinks_when_it_is_not_on_gemfile
- template = Tempfile.open 'my_template'
- template.puts 'add_gem_entry_filter { |gem| gem.name != "turbolinks" }'
- template.flush
+ def test_remove_gem
+ Tempfile.open 'my_template' do |template|
+ template.puts 'remove_gem "jbuilder"'
+ template.close
- run_generator([destination_root, "-m", template.path])
- assert_file "Gemfile" do |contents|
- assert_no_match 'turbolinks', contents
+ run_generator([destination_root, "-n", template.path])
+ assert_file "Gemfile" do |contents|
+ assert_no_match 'jbuilder', contents
+ end
end
+ end
- assert_file "app/views/layouts/application.html.erb" do |contents|
- assert_no_match 'turbolinks', contents
- end
+ def test_skip_turbolinks_when_it_is_not_on_gemfile
+ Tempfile.open 'my_template' do |template|
+ template.puts 'add_gem_entry_filter { |gem| gem.name != "turbolinks" }'
+ template.flush
- assert_file "app/views/layouts/application.html.erb" do |contents|
- assert_no_match('data-turbolinks-track', contents)
- end
+ run_generator([destination_root, "-n", template.path])
+ assert_file "Gemfile" do |contents|
+ assert_no_match 'turbolinks', contents
+ end
- assert_file "app/assets/javascripts/application.js" do |contents|
- assert_no_match 'turbolinks', contents
+ assert_file "app/views/layouts/application.html.erb" do |contents|
+ assert_no_match 'turbolinks', contents
+ end
+
+ assert_file "app/views/layouts/application.html.erb" do |contents|
+ assert_no_match('data-turbolinks-track', contents)
+ end
+
+ assert_file "app/assets/javascripts/application.js" do |contents|
+ assert_no_match 'turbolinks', contents
+ end
end
- ensure
- template.close
- template.unlink
end
def test_config_another_database
@@ -291,7 +306,6 @@ class AppGeneratorTest < Rails::Generators::TestCase
run_generator [destination_root, "--skip-sprockets"]
assert_file "config/application.rb" do |content|
assert_match(/#\s+require\s+["']sprockets\/railtie["']/, content)
- assert_match(/config\.assets\.enabled = false/, content)
end
assert_file "Gemfile" do |content|
assert_no_match(/sass-rails/, content)
@@ -438,6 +452,34 @@ class AppGeneratorTest < Rails::Generators::TestCase
assert_file "foo bar/config/initializers/session_store.rb", /key: '_foo_bar/
end
+ def test_spring
+ run_generator
+ assert_file "Gemfile", /gem 'spring', \s+group: :development/
+ end
+
+ def test_spring_binstubs
+ generator.stubs(:bundle_command).with('install')
+ generator.expects(:bundle_command).with('exec spring binstub --all').once
+ quietly { generator.invoke_all }
+ end
+
+ def test_spring_no_fork
+ Process.stubs(:respond_to?).with(:fork).returns(false)
+ run_generator
+
+ assert_file "Gemfile" do |content|
+ assert_no_match(/spring/, content)
+ end
+ end
+
+ def test_skip_spring
+ run_generator [destination_root, "--skip-spring"]
+
+ assert_file "Gemfile" do |content|
+ assert_no_match(/spring/, content)
+ end
+ end
+
protected
def action(*args, &block)
diff --git a/railties/test/generators/generators_test_helper.rb b/railties/test/generators/generators_test_helper.rb
index 32a3d072c9..77ec2f1c0c 100644
--- a/railties/test/generators/generators_test_helper.rb
+++ b/railties/test/generators/generators_test_helper.rb
@@ -1,10 +1,14 @@
require 'abstract_unit'
+require 'active_support/core_ext/module/remove_method'
require 'rails/generators'
require 'rails/generators/test_case'
module Rails
- def self.root
- @root ||= File.expand_path(File.join(File.dirname(__FILE__), '..', 'fixtures'))
+ class << self
+ remove_possible_method :root
+ def root
+ @root ||= File.expand_path(File.join(File.dirname(__FILE__), '..', 'fixtures'))
+ end
end
end
Rails.application.config.root = Rails.root
diff --git a/railties/test/generators/mailer_generator_test.rb b/railties/test/generators/mailer_generator_test.rb
index 6b2351fc1a..d209801f60 100644
--- a/railties/test/generators/mailer_generator_test.rb
+++ b/railties/test/generators/mailer_generator_test.rb
@@ -1,7 +1,6 @@
require 'generators/generators_test_helper'
require 'rails/generators/mailer/mailer_generator'
-
class MailerGeneratorTest < Rails::Generators::TestCase
include GeneratorsTestHelper
arguments %w(notifier foo bar)
@@ -23,8 +22,11 @@ class MailerGeneratorTest < Rails::Generators::TestCase
end
def test_check_class_collision
- content = capture(:stderr){ run_generator ["object"] }
- assert_match(/The name 'Object' is either already used in your application or reserved/, content)
+ Object.send :const_set, :Notifier, Class.new
+ content = capture(:stderr){ run_generator }
+ assert_match(/The name 'Notifier' is either already used in your application or reserved/, content)
+ ensure
+ Object.send :remove_const, :Notifier
end
def test_invokes_default_test_framework
@@ -34,9 +36,37 @@ class MailerGeneratorTest < Rails::Generators::TestCase
assert_match(/test "foo"/, test)
assert_match(/test "bar"/, test)
end
+ assert_file "test/mailers/previews/notifier_preview.rb" do |preview|
+ assert_match(/\# Preview all emails at http:\/\/localhost\:3000\/rails\/mailers\/notifier/, preview)
+ assert_match(/class NotifierPreview < ActionMailer::Preview/, preview)
+ assert_match(/\# Preview this email at http:\/\/localhost\:3000\/rails\/mailers\/notifier\/foo/, preview)
+ assert_instance_method :foo, preview do |foo|
+ assert_match(/Notifier.foo/, foo)
+ end
+ assert_match(/\# Preview this email at http:\/\/localhost\:3000\/rails\/mailers\/notifier\/bar/, preview)
+ assert_instance_method :bar, preview do |bar|
+ assert_match(/Notifier.bar/, bar)
+ end
+ end
end
- def test_invokes_default_template_engine
+ def test_check_test_class_collision
+ Object.send :const_set, :NotifierTest, Class.new
+ content = capture(:stderr){ run_generator }
+ assert_match(/The name 'NotifierTest' is either already used in your application or reserved/, content)
+ ensure
+ Object.send :remove_const, :NotifierTest
+ end
+
+ def test_check_preview_class_collision
+ Object.send :const_set, :NotifierPreview, Class.new
+ content = capture(:stderr){ run_generator }
+ assert_match(/The name 'NotifierPreview' is either already used in your application or reserved/, content)
+ ensure
+ Object.send :remove_const, :NotifierPreview
+ end
+
+ def test_invokes_default_text_template_engine
run_generator
assert_file "app/views/notifier/foo.text.erb" do |view|
assert_match(%r(app/views/notifier/foo\.text\.erb), view)
@@ -49,6 +79,19 @@ class MailerGeneratorTest < Rails::Generators::TestCase
end
end
+ def test_invokes_default_html_template_engine
+ run_generator
+ assert_file "app/views/notifier/foo.html.erb" do |view|
+ assert_match(%r(app/views/notifier/foo\.html\.erb), view)
+ assert_match(/<%= @greeting %>/, view)
+ end
+
+ assert_file "app/views/notifier/bar.html.erb" do |view|
+ assert_match(%r(app/views/notifier/bar\.html\.erb), view)
+ assert_match(/<%= @greeting %>/, view)
+ end
+ end
+
def test_invokes_default_template_engine_even_with_no_action
run_generator ["notifier"]
assert_file "app/views/notifier"
@@ -65,7 +108,13 @@ class MailerGeneratorTest < Rails::Generators::TestCase
assert_match(/class Farm::Animal < ActionMailer::Base/, mailer)
assert_match(/en\.farm\.animal\.moos\.subject/, mailer)
end
+ assert_file "test/mailers/previews/farm/animal_preview.rb" do |preview|
+ assert_match(/\# Preview all emails at http:\/\/localhost\:3000\/rails\/mailers\/farm\/animal/, preview)
+ assert_match(/class Farm::AnimalPreview < ActionMailer::Preview/, preview)
+ assert_match(/\# Preview this email at http:\/\/localhost\:3000\/rails\/mailers\/farm\/animal\/moos/, preview)
+ end
assert_file "app/views/farm/animal/moos.text.erb"
+ assert_file "app/views/farm/animal/moos.html.erb"
end
def test_actions_are_turned_into_methods
diff --git a/railties/test/generators/plugin_generator_test.rb b/railties/test/generators/plugin_generator_test.rb
index c6b91e7cba..932cd75bcb 100644
--- a/railties/test/generators/plugin_generator_test.rb
+++ b/railties/test/generators/plugin_generator_test.rb
@@ -35,6 +35,12 @@ class PluginGeneratorTest < Rails::Generators::TestCase
content = capture(:stderr){ run_generator [File.join(destination_root, "43things")] }
assert_equal "Invalid plugin name 43things. Please give a name which does not start with numbers.\n", content
+
+ content = capture(:stderr){ run_generator [File.join(destination_root, "plugin")] }
+ assert_equal "Invalid plugin name plugin. Please give a name which does not match one of the reserved rails words.\n", content
+
+ content = capture(:stderr){ run_generator [File.join(destination_root, "Digest")] }
+ assert_equal "Invalid plugin name Digest, constant Digest is already in use. Please choose another plugin name.\n", content
end
def test_camelcase_plugin_name_underscores_filenames
@@ -58,6 +64,17 @@ class PluginGeneratorTest < Rails::Generators::TestCase
assert_file "test/integration/navigation_test.rb", /ActionDispatch::IntegrationTest/
end
+ def test_inclusion_of_debugger
+ run_generator [destination_root, '--full']
+ if defined?(JRUBY_VERSION)
+ assert_file "Gemfile" do |content|
+ assert_no_match(/debugger/, content)
+ end
+ else
+ assert_file "Gemfile", /# gem 'debugger'/
+ end
+ end
+
def test_generating_test_files_in_full_mode_without_unit_test_files
run_generator [destination_root, "-T", "--full"]
@@ -309,7 +326,7 @@ class PluginGeneratorTest < Rails::Generators::TestCase
end
def test_creating_plugin_in_app_directory_adds_gemfile_entry
- # simulate application existance
+ # simulate application existence
gemfile_path = "#{Rails.root}/Gemfile"
Object.const_set('APP_PATH', Rails.root)
FileUtils.touch gemfile_path
@@ -323,7 +340,7 @@ class PluginGeneratorTest < Rails::Generators::TestCase
end
def test_skipping_gemfile_entry
- # simulate application existance
+ # simulate application existence
gemfile_path = "#{Rails.root}/Gemfile"
Object.const_set('APP_PATH', Rails.root)
FileUtils.touch gemfile_path
diff --git a/railties/test/generators/shared_generator_tests.rb b/railties/test/generators/shared_generator_tests.rb
index 7184639d23..8e198d5fe1 100644
--- a/railties/test/generators/shared_generator_tests.rb
+++ b/railties/test/generators/shared_generator_tests.rb
@@ -26,11 +26,17 @@ module SharedGeneratorTests
default_files.each { |path| assert_file path }
end
- def test_generation_runs_bundle_install
- generator([destination_root]).expects(:bundle_command).with('install').once
+ def assert_generates_with_bundler(options = {})
+ generator([destination_root], options)
+ generator.expects(:bundle_command).with('install').once
+ generator.stubs(:bundle_command).with('exec spring binstub --all')
quietly { generator.invoke_all }
end
+ def test_generation_runs_bundle_install
+ assert_generates_with_bundler
+ end
+
def test_plugin_new_generate_pretend
run_generator ["testapp", "--pretend"]
default_files.each{ |path| assert_no_file File.join("testapp",path) }
@@ -96,15 +102,13 @@ module SharedGeneratorTests
end
def test_dev_option
- generator([destination_root], dev: true).expects(:bundle_command).with('install').once
- quietly { generator.invoke_all }
+ assert_generates_with_bundler dev: true
rails_path = File.expand_path('../../..', Rails.root)
assert_file 'Gemfile', /^gem\s+["']rails["'],\s+path:\s+["']#{Regexp.escape(rails_path)}["']$/
end
def test_edge_option
- generator([destination_root], edge: true).expects(:bundle_command).with('install').once
- quietly { generator.invoke_all }
+ assert_generates_with_bundler edge: true
assert_file 'Gemfile', %r{^gem\s+["']rails["'],\s+github:\s+["']#{Regexp.escape("rails/rails")}["']$}
end
diff --git a/railties/test/isolation/abstract_unit.rb b/railties/test/isolation/abstract_unit.rb
index 913e2b5e29..a1f1973563 100644
--- a/railties/test/isolation/abstract_unit.rb
+++ b/railties/test/isolation/abstract_unit.rb
@@ -93,7 +93,8 @@ module TestHelpers
# Build an application by invoking the generator and going through the whole stack.
def build_app(options = {})
@prev_rails_env = ENV['RAILS_ENV']
- ENV['RAILS_ENV'] = 'development'
+ ENV['RAILS_ENV'] = 'development'
+ ENV['RAILS_SECRET_KEY_BASE'] ||= SecureRandom.hex(16)
FileUtils.rm_rf(app_path)
FileUtils.cp_r(app_template_path, app_path)
@@ -117,9 +118,26 @@ module TestHelpers
end
end
+ File.open("#{app_path}/config/database.yml", "w") do |f|
+ f.puts <<-YAML
+ default: &default
+ adapter: sqlite3
+ pool: 5
+ timeout: 5000
+ development:
+ <<: *default
+ database: db/development.sqlite3
+ test:
+ <<: *default
+ database: db/test.sqlite3
+ production:
+ <<: *default
+ database: db/production.sqlite3
+ YAML
+ end
+
add_to_config <<-RUBY
config.eager_load = false
- config.secret_key_base = "3b7cd727ee24e8444053437c36cc66c4"
config.session_store :cookie_store, key: "_myapp_session"
config.active_support.deprecation = :log
config.action_controller.allow_forgery_protection = false
@@ -139,7 +157,7 @@ module TestHelpers
app = Class.new(Rails::Application)
app.config.eager_load = false
- app.config.secret_key_base = "3b7cd727ee24e8444053437c36cc66c4"
+ app.secrets.secret_key_base = "3b7cd727ee24e8444053437c36cc66c4"
app.config.session_store :cookie_store, key: "_myapp_session"
app.config.active_support.deprecation = :log
diff --git a/railties/test/rails_info_controller_test.rb b/railties/test/rails_info_controller_test.rb
index e45a5228a1..a9b237d0a5 100644
--- a/railties/test/rails_info_controller_test.rb
+++ b/railties/test/rails_info_controller_test.rb
@@ -1,7 +1,5 @@
require 'abstract_unit'
-ActionController::Base.superclass.send(:include, ActionView::Layouts)
-
module ActionController
class Base
include ActionController::Testing