diff options
author | Aaron Patterson <aaron.patterson@gmail.com> | 2014-01-11 17:28:43 -0800 |
---|---|---|
committer | Aaron Patterson <aaron.patterson@gmail.com> | 2014-01-11 17:28:43 -0800 |
commit | 11e8badb16876e6bd72c874631d25aec41dad293 (patch) | |
tree | 5ec87baa3a8e7652c46d6804b174b81b8f9c7745 /railties/lib | |
parent | 474ebc55bd13ad58626a49dfc44c8e6407813935 (diff) | |
parent | caa981d88112f019ade868f75af6b5f399c244a4 (diff) | |
download | rails-11e8badb16876e6bd72c874631d25aec41dad293.tar.gz rails-11e8badb16876e6bd72c874631d25aec41dad293.tar.bz2 rails-11e8badb16876e6bd72c874631d25aec41dad293.zip |
Merge branch 'master' into set_binds
* master: (2794 commits)
doc, API example on how to use `Model#exists?` with multiple IDs. [ci skip]
Restore DATABASE_URL even if it's nil in connection_handler test
[ci skip] - error_messages_for has been deprecated since 2.3.8 - lets reduce any confusion for users
Ensure Active Record connection consistency
Revert "ask the fixture set for the sql statements"
Check `respond_to` before delegation due to: https://github.com/ruby/ruby/commit/d781caaf313b8649948c107bba277e5ad7307314
Adding Hash#compact and Hash#compact! methods
MySQL version 4.1 was EOL on December 31, 2009 We should at least recommend modern versions of MySQL to users.
clear cache on body close so that cache remains during rendering
add a more restricted codepath for templates fixes #13390
refactor generator tests to use block form of Tempfile
Fix typo [ci skip]
Move finish_template as the last public method in the generator
Minor typos fix [ci skip]
make `change_column_null` reversible. Closes #13576.
create/drop test and development databases only if RAILS_ENV is nil
Revert "Speedup String#to"
typo fix in test name. [ci skip].
`core_ext/string/access.rb` test what we are documenting.
Fix typo in image_tag documentation
...
Conflicts:
activerecord/lib/active_record/associations/join_dependency/join_association.rb
activerecord/lib/active_record/relation/query_methods.rb
Diffstat (limited to 'railties/lib')
131 files changed, 1793 insertions, 994 deletions
diff --git a/railties/lib/rails.rb b/railties/lib/rails.rb index bb98bbe5bf..be7570a5ba 100644 --- a/railties/lib/rails.rb +++ b/railties/lib/rails.rb @@ -3,12 +3,13 @@ require 'rails/ruby_version_check' require 'pathname' require 'active_support' +require 'active_support/dependencies/autoload' require 'active_support/core_ext/kernel/reporting' +require 'active_support/core_ext/module/delegation' require 'active_support/core_ext/array/extract_options' require 'rails/application' require 'rails/version' -require 'rails/deprecation' require 'active_support/railtie' require 'action_dispatch/railtie' @@ -20,26 +21,23 @@ silence_warnings do end module Rails - autoload :Info, 'rails/info' - autoload :InfoController, 'rails/info_controller' - autoload :WelcomeController, 'rails/welcome_controller' + extend ActiveSupport::Autoload + + autoload :Info + autoload :InfoController + autoload :MailersController + autoload :WelcomeController class << self attr_accessor :application, :cache, :logger + delegate :initialize!, :initialized?, to: :application + # The Configuration instance used to configure the Rails environment def configuration application.config end - def initialize! - application.initialize! - end - - def initialized? - application.initialized? - end - def backtrace_cleaner @backtrace_cleaner ||= begin # Relies on Active Support, so we have to lazy load to postpone definition until AS has been loaded @@ -76,7 +74,7 @@ module Rails env = Rails.env groups.unshift(:default, env) groups.concat ENV["RAILS_GROUPS"].to_s.split(",") - groups.concat hash.map { |k,v| k if v.map(&:to_s).include?(env) } + groups.concat hash.map { |k, v| k if v.map(&:to_s).include?(env) } groups.compact! groups.uniq! groups diff --git a/railties/lib/rails/all.rb b/railties/lib/rails/all.rb index 6c9c53fc69..2e83c0fe14 100644 --- a/railties/lib/rails/all.rb +++ b/railties/lib/rails/all.rb @@ -3,6 +3,7 @@ require "rails" %w( active_record action_controller + action_view action_mailer rails/test_unit sprockets diff --git a/railties/lib/rails/api/task.rb b/railties/lib/rails/api/task.rb index c829873da4..3e32576040 100644 --- a/railties/lib/rails/api/task.rb +++ b/railties/lib/rails/api/task.rb @@ -7,7 +7,6 @@ module Rails 'activesupport' => { :include => %w( README.rdoc - CHANGELOG.md lib/active_support/**/*.rb ), :exclude => 'lib/active_support/vendor/*' @@ -16,16 +15,13 @@ module Rails 'activerecord' => { :include => %w( README.rdoc - CHANGELOG.md lib/active_record/**/*.rb - ), - :exclude => 'lib/active_record/vendor/*' + ) }, 'activemodel' => { :include => %w( README.rdoc - CHANGELOG.md lib/active_model/**/*.rb ) }, @@ -33,29 +29,30 @@ module Rails 'actionpack' => { :include => %w( README.rdoc - CHANGELOG.md lib/abstract_controller/**/*.rb lib/action_controller/**/*.rb lib/action_dispatch/**/*.rb + ) + }, + + 'actionview' => { + :include => %w( + README.rdoc lib/action_view/**/*.rb ), - :exclude => 'lib/action_controller/vendor/*' + :exclude => 'lib/action_view/vendor/*' }, 'actionmailer' => { :include => %w( README.rdoc - CHANGELOG.md lib/action_mailer/**/*.rb - ), - :exclude => 'lib/action_mailer/vendor/*' + ) }, 'railties' => { :include => %w( README.rdoc - CHANGELOG.md - MIT-LICENSE lib/**/*.rb ), :exclude => 'lib/rails/generators/rails/**/templates/**/*.rb' @@ -135,12 +132,20 @@ module Rails def api_dir 'doc/rdoc' end + end + class EdgeTask < RepoTask def rails_version "master@#{`git rev-parse HEAD`[0, 7]}" end end + class StableTask < RepoTask + def rails_version + File.read('RAILS_VERSION').strip + end + end + class AppTask < Task def component_root_dir(gem_name) $:.grep(%r{#{gem_name}[\w.-]*/lib\z}).first[0..-5] diff --git a/railties/lib/rails/app_rails_loader.rb b/railties/lib/rails/app_rails_loader.rb index 4a17803f1c..1610751844 100644 --- a/railties/lib/rails/app_rails_loader.rb +++ b/railties/lib/rails/app_rails_loader.rb @@ -2,7 +2,7 @@ require 'pathname' module Rails module AppRailsLoader - RUBY = File.join(*RbConfig::CONFIG.values_at("bindir", "ruby_install_name")) + RbConfig::CONFIG["EXEEXT"] + RUBY = Gem.ruby EXECUTABLES = ['bin/rails', 'script/rails'] BUNDLER_WARNING = <<EOS Looks like your app's ./bin/rails is a stub that was generated by Bundler. @@ -49,13 +49,13 @@ EOS # call to generate a new application, so restore the original cwd. Dir.chdir(original_cwd) and return if Pathname.new(Dir.pwd).root? - # Otherwise keep moving upwards in search of a executable. + # Otherwise keep moving upwards in search of an executable. Dir.chdir('..') end end def self.find_executable - EXECUTABLES.find { |exe| File.exists?(exe) } + EXECUTABLES.find { |exe| File.exist?(exe) } end end end diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 914e4393c4..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 @@ -51,21 +53,49 @@ module Rails # 10) Run config.before_eager_load and eager_load! if eager_load is true # 11) Run config.after_initialize callbacks # + # == Multiple Applications + # + # If you decide to define multiple applications, then the first application + # that is initialized will be set to +Rails.application+, unless you override + # it with a different application. + # + # To create a new application, you can instantiate a new instance of a class + # that has already been created: + # + # class Application < Rails::Application + # end + # + # first_application = Application.new + # second_application = Application.new(config: first_application.config) + # + # In the above example, the configuration from the first application was used + # to initialize the second application. You can also use the +initialize_copy+ + # on one of the applications to create a copy of the application which shares + # the configuration. + # + # If you decide to define rake tasks, runners, or initializers in an + # application other than +Rails.application+, then you must run those + # these manually. class Application < Engine - autoload :Bootstrap, 'rails/application/bootstrap' - autoload :Configuration, 'rails/application/configuration' - autoload :Finisher, 'rails/application/finisher' - autoload :Railties, 'rails/engine/railties' - autoload :RoutesReloader, 'rails/application/routes_reloader' + autoload :Bootstrap, 'rails/application/bootstrap' + autoload :Configuration, 'rails/application/configuration' + autoload :DefaultMiddlewareStack, 'rails/application/default_middleware_stack' + autoload :Finisher, 'rails/application/finisher' + autoload :Railties, 'rails/engine/railties' + autoload :RoutesReloader, 'rails/application/routes_reloader' class << self def inherited(base) - raise "You cannot have more than one Rails::Application" if Rails.application super - Rails.application = base.instance - Rails.application.add_lib_to_load_path! - ActiveSupport.run_load_hooks(:before_configuration, base.instance) + Rails.application ||= base.instance end + + # Makes the +new+ method public. + # + # Note that Rails::Application inherits from Rails::Engine, which + # inherits from Rails::Railtie and the +new+ method on Rails::Railtie is + # private + public :new end attr_accessor :assets, :sandbox @@ -74,14 +104,29 @@ module Rails delegate :default_url_options, :default_url_options=, to: :routes - def initialize - super - @initialized = false - @reloaders = [] - @routes_reloader = nil - @app_env_config = nil - @ordered_railties = nil - @railties = nil + INITIAL_VARIABLES = [:config, :railties, :routes_reloader, :reloaders, + :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 + @message_verifiers = {} + + add_lib_to_load_path! + ActiveSupport.run_load_hooks(:before_configuration, self) + + initial_variable_values.each do |variable_name, value| + if INITIAL_VARIABLES.include?(variable_name) + instance_variable_set("@#{variable_name}", value) + end + end + + instance_eval(&block) if block_given? end # Returns true if the application is initialized. @@ -102,14 +147,13 @@ module Rails routes_reloader.reload! end - # Return the application's KeyGenerator def key_generator # 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) @@ -117,40 +161,42 @@ module Rails end end - # Stores some of the Rails initial environment parameters which - # will be used by middlewares and engines to configure themselves. - # Currently stores: + # 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. # - # * "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.show_exceptions" => config.action_dispatch.show_exceptions - # * "action_dispatch.show_detailed_exceptions" => config.consider_all_requests_local - # * "action_dispatch.logger" => Rails.logger - # * "action_dispatch.backtrace_cleaner" => Rails.backtrace_cleaner - # * "action_dispatch.key_generator" => key_generator - # * "action_dispatch.http_auth_salt" => config.action_dispatch.http_auth_salt - # * "action_dispatch.signed_cookie_salt" => config.action_dispatch.signed_cookie_salt - # * "action_dispatch.encrypted_cookie_salt" => config.action_dispatch.encrypted_cookie_salt - # * "action_dispatch.encrypted_signed_cookie_salt" => config.action_dispatch.encrypted_signed_cookie_salt + # ==== 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 @app_env_config ||= begin - if config.secret_key_base.blank? - ActiveSupport::Deprecation.warn "You didn't set config.secret_key_base. " + - "Read the upgrade documentation to learn more about this new config option." - - if config.secret_token.blank? - raise "You must set config.secret_key_base in your app's config." - end - end + validate_secret_key_config! super.merge({ "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, @@ -164,6 +210,30 @@ module Rails end end + # If you try to define a set of rake tasks on the instance, these will get + # passed up to the rake tasks defined on the application's class. + def rake_tasks(&block) + self.class.rake_tasks(&block) + end + + # Sends the initializers to the +initializer+ method defined in the + # Rails::Initializable module. Each Rails::Application class has its own + # set of initializers, as defined by the Initializable module. + def initializer(name, opts={}, &block) + self.class.initializer(name, opts, &block) + end + + # Sends any runner called in the instance of a new application up + # to the +runner+ method defined in Rails::Railtie. + def runner(&blk) + self.class.runner(&blk) + end + + # Sends the +isolate_namespace+ method up to the class method. + def isolate_namespace(mod) + self.class.isolate_namespace(mod) + end + ## Rails internal API # This method is called just after an application inherits from Rails::Application, @@ -181,7 +251,9 @@ module Rails # you need to load files in lib/ during the application configuration as well. def add_lib_to_load_path! #:nodoc: path = File.join config.root, 'lib' - $LOAD_PATH.unshift(path) if File.exists?(path) + if File.exist?(path) && !$LOAD_PATH.include?(path) + $LOAD_PATH.unshift(path) + end end def require_environment! #:nodoc: @@ -207,9 +279,7 @@ module Rails end # Initialize the application passing the given group. By default, the - # group is :default but sprockets precompilation passes group equals - # to assets if initialize_on_precompile is false to avoid booting the - # whole app. + # group is :default def initialize!(group=:default) #:nodoc: raise "Application has been already initialized." if @initialized run_initializers(group, self) @@ -227,6 +297,31 @@ module Rails @config ||= Application::Configuration.new(find_root_with_flag("config.ru", Dir.pwd)) end + def config=(configuration) #:nodoc: + @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 @@ -243,9 +338,9 @@ module Rails railties.each { |r| r.run_tasks_blocks(app) } super require "rails/tasks" - config = self.config task :environment do - config.eager_load = false + ActiveSupport.on_load(:before_initialize) { config.eager_load = false } + require_environment! end end @@ -300,96 +395,9 @@ module Rails initializers end - def reload_dependencies? #:nodoc: - config.reload_classes_only_on_change != true || reloaders.map(&:updated?).any? - end - def default_middleware_stack #:nodoc: - ActionDispatch::MiddlewareStack.new.tap do |middleware| - app = self - - 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 - - if config.action_dispatch.x_sendfile_header.present? - middleware.use ::Rack::Sendfile, config.action_dispatch.x_sendfile_header - end - - if config.serve_static_assets - middleware.use ::ActionDispatch::Static, paths["public"].first, config.static_cache_control - end - - middleware.use ::Rack::Lock unless allow_concurrency? - middleware.use ::Rack::Runtime - middleware.use ::Rack::MethodOverride - middleware.use ::ActionDispatch::RequestId - - # Must come after Rack::MethodOverride to properly log overridden methods - middleware.use ::Rails::Rack::Logger, config.log_tags - middleware.use ::ActionDispatch::ShowExceptions, show_exceptions_app - middleware.use ::ActionDispatch::DebugExceptions, app - middleware.use ::ActionDispatch::RemoteIp, config.action_dispatch.ip_spoofing_check, config.action_dispatch.trusted_proxies - - unless config.cache_classes - middleware.use ::ActionDispatch::Reloader, lambda { app.reload_dependencies? } - end - - middleware.use ::ActionDispatch::Callbacks - middleware.use ::ActionDispatch::Cookies - - if config.session_store - if config.force_ssl && !config.session_options.key?(:secure) - config.session_options[:secure] = true - end - middleware.use config.session_store, config.session_options - middleware.use ::ActionDispatch::Flash - end - - middleware.use ::ActionDispatch::ParamsParser - middleware.use ::Rack::Head - middleware.use ::Rack::ConditionalGet - middleware.use ::Rack::ETag, "no-cache" - end - end - - def allow_concurrency? - if config.allow_concurrency.nil? - config.cache_classes - else - config.allow_concurrency - end - end - - def load_rack_cache - rack_cache = config.action_dispatch.rack_cache - return unless rack_cache - - begin - require 'rack/cache' - rescue LoadError => error - error.message << ' Be sure to add rack-cache to your Gemfile' - raise - end - - if rack_cache == true - { - metastore: "rails:/", - entitystore: "rails:/", - verbose: false - } - else - rack_cache - end - end - - def show_exceptions_app - config.exceptions_app || ActionDispatch::PublicExceptions.new(Rails.public_path) + default_stack = DefaultMiddlewareStack.new(self, config, paths) + default_stack.build_stack end def build_original_fullpath(env) #:nodoc: @@ -403,5 +411,11 @@ module Rails "#{script_name}#{path_info}" end end + + def validate_secret_key_config! #:nodoc: + 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 end diff --git a/railties/lib/rails/application/bootstrap.rb b/railties/lib/rails/application/bootstrap.rb index 62d57c0cc6..a26d41c0cf 100644 --- a/railties/lib/rails/application/bootstrap.rb +++ b/railties/lib/rails/application/bootstrap.rb @@ -42,7 +42,6 @@ INFO logger = ActiveSupport::Logger.new f logger.formatter = config.log_formatter logger = ActiveSupport::TaggedLogging.new(logger) - logger.level = ActiveSupport::Logger.const_get(config.log_level.to_s.upcase) logger rescue StandardError logger = ActiveSupport::TaggedLogging.new(ActiveSupport::Logger.new(STDERR)) @@ -53,6 +52,8 @@ INFO ) logger end + + Rails.logger.level = ActiveSupport::Logger.const_get(config.log_level.to_s.upcase) end # Initialize cache early in the stack so railties can make use of it. diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb index 31fc80e544..e902205a13 100644 --- a/railties/lib/rails/application/configuration.rb +++ b/railties/lib/rails/application/configuration.rb @@ -61,7 +61,6 @@ module Rails @assets.cache_store = [ :file_store, "#{root}/tmp/cache/assets/#{Rails.env}/" ] @assets.js_compressor = nil @assets.css_compressor = nil - @assets.initialize_on_precompile = true @assets.logger = nil end @@ -77,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" @@ -88,27 +88,23 @@ module Rails end end - def threadsafe! - message = "config.threadsafe! is deprecated. Rails applications " \ - "behave by default as thread safe in production as long as config.cache_classes and " \ - "config.eager_load are set to true" - ActiveSupport::Deprecation.warn message - @cache_classes = true - @eager_load = true - self - 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.exists?(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. " \ @@ -151,9 +147,6 @@ module Rails end end - def whiny_nils=(*) - ActiveSupport::Deprecation.warn "config.whiny_nils option is deprecated and no longer works" - end end end end diff --git a/railties/lib/rails/application/default_middleware_stack.rb b/railties/lib/rails/application/default_middleware_stack.rb new file mode 100644 index 0000000000..a00afe008c --- /dev/null +++ b/railties/lib/rails/application/default_middleware_stack.rb @@ -0,0 +1,99 @@ +module Rails + class Application + class DefaultMiddlewareStack + attr_reader :config, :paths, :app + + def initialize(app, config, paths) + @app = app + @config = config + @paths = paths + end + + def build_stack + ActionDispatch::MiddlewareStack.new.tap do |middleware| + if config.force_ssl + middleware.use ::ActionDispatch::SSL, config.ssl_options + end + + middleware.use ::Rack::Sendfile, config.action_dispatch.x_sendfile_header + + if config.serve_static_assets + 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 + middleware.use ::ActionDispatch::RequestId + + # Must come after Rack::MethodOverride to properly log overridden methods + middleware.use ::Rails::Rack::Logger, config.log_tags + middleware.use ::ActionDispatch::ShowExceptions, show_exceptions_app + middleware.use ::ActionDispatch::DebugExceptions, app + middleware.use ::ActionDispatch::RemoteIp, config.action_dispatch.ip_spoofing_check, config.action_dispatch.trusted_proxies + + unless config.cache_classes + middleware.use ::ActionDispatch::Reloader, lambda { reload_dependencies? } + end + + middleware.use ::ActionDispatch::Callbacks + middleware.use ::ActionDispatch::Cookies + + if config.session_store + if config.force_ssl && !config.session_options.key?(:secure) + config.session_options[:secure] = true + end + middleware.use config.session_store, config.session_options + middleware.use ::ActionDispatch::Flash + end + + middleware.use ::ActionDispatch::ParamsParser + middleware.use ::Rack::Head + middleware.use ::Rack::ConditionalGet + middleware.use ::Rack::ETag, "no-cache" + end + end + + private + + def reload_dependencies? + config.reload_classes_only_on_change != true || app.reloaders.map(&:updated?).any? + end + + def allow_concurrency? + config.allow_concurrency.nil? ? config.cache_classes : config.allow_concurrency + end + + def load_rack_cache + rack_cache = config.action_dispatch.rack_cache + return unless rack_cache + + begin + require 'rack/cache' + rescue LoadError => error + error.message << ' Be sure to add rack-cache to your Gemfile' + raise + end + + if rack_cache == true + { + metastore: "rails:/", + entitystore: "rails:/", + verbose: false + } + else + rack_cache + end + end + + def show_exceptions_app + config.exceptions_app || ActionDispatch::PublicExceptions.new(Rails.public_path) + end + end + end +end diff --git a/railties/lib/rails/application/finisher.rb b/railties/lib/rails/application/finisher.rb index 3ae60312c5..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" @@ -62,17 +64,28 @@ module Rails ActiveSupport.run_load_hooks(:after_initialize, self) end - # Set app reload just after the finisher hook to ensure - # routes added in the hook are still loaded. + # Set routes reload after the finisher hook to ensure routes added in + # the hook are taken into account. initializer :set_routes_reloader_hook do reloader = routes_reloader reloader.execute_if_updated self.reloaders << reloader - ActionDispatch::Reloader.to_prepare { reloader.execute_if_updated } + ActionDispatch::Reloader.to_prepare do + # We configure #execute rather than #execute_if_updated because if + # autoloaded constants are cleared we need to reload routes also in + # case any was used there, as in + # + # mount MailPreview => 'mail_view' + # + # This means routes are also reloaded if i18n is updated, which + # might not be necessary, but in order to be more precise we need + # some sort of reloaders dependency support, to be added. + reloader.execute + end end - # Set app reload just after the finisher hook to ensure - # paths added in the hook are still loaded. + # Set clearing dependencies after the finisher hook to ensure paths + # added in the hook are taken into account. initializer :set_clear_dependencies_hook, group: :all do callback = lambda do ActiveSupport::DescendantsTracker.clear @@ -82,9 +95,17 @@ module Rails if config.reload_classes_only_on_change reloader = config.file_watcher.new(*watchable_args, &callback) self.reloaders << reloader - # We need to set a to_prepare callback regardless of the reloader result, i.e. - # models should be reloaded if any of the reloaders (i18n, routes) were updated. - ActionDispatch::Reloader.to_prepare(prepend: true){ reloader.execute } + + # Prepend this callback to have autoloaded constants cleared before + # any other possible reloading, in case they need to autoload fresh + # constants. + ActionDispatch::Reloader.to_prepare(prepend: true) do + # In addition to changes detected by the file watcher, if routes + # or i18n have been updated we also need to clear constants, + # that's why we run #execute rather than #execute_if_updated, this + # callback has to clear autoloaded constants after any update. + reloader.execute + end else ActionDispatch::Reloader.to_cleanup(&callback) end 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/cli.rb b/railties/lib/rails/cli.rb index e5341ac436..dd70c272c6 100644 --- a/railties/lib/rails/cli.rb +++ b/railties/lib/rails/cli.rb @@ -1,4 +1,3 @@ -require 'rbconfig' require 'rails/app_rails_loader' # If we are inside a Rails application this method performs an exec and thus @@ -10,7 +9,7 @@ Signal.trap("INT") { puts; exit(1) } if ARGV.first == 'plugin' ARGV.shift - require 'rails/commands/plugin_new' + require 'rails/commands/plugin' else require 'rails/commands/application' end diff --git a/railties/lib/rails/commands.rb b/railties/lib/rails/commands.rb index e8c42b149b..f32bf772a5 100644 --- a/railties/lib/rails/commands.rb +++ b/railties/lib/rails/commands.rb @@ -5,109 +5,13 @@ aliases = { "d" => "destroy", "c" => "console", "s" => "server", - "t" => "test", "db" => "dbconsole", "r" => "runner" } -help_message = <<-EOT -Usage: rails COMMAND [ARGS] - -The most common rails commands are: - generate Generate new code (short-cut alias: "g") - console Start the Rails console (short-cut alias: "c") - server Start the Rails server (short-cut alias: "s") - test Running the test file (short-cut alias: "t") - dbconsole Start a console for the database specified in config/database.yml - (short-cut alias: "db") - new Create a new Rails application. "rails new my_app" creates a - new application called MyApp in "./my_app" - -In addition to those, there are: - application Generate the Rails application code - destroy Undo code generated with "generate" (short-cut alias: "d") - plugin new Generates skeleton for developing a Rails plugin - runner Run a piece of code in the application environment (short-cut alias: "r") - -All commands can be run with -h (or --help) for more information. -EOT - - command = ARGV.shift command = aliases[command] || command -case command -when 'generate', 'destroy', 'plugin' - require 'rails/generators' - - if command == 'plugin' && ARGV.first == 'new' - require "rails/commands/plugin_new" - else - require APP_PATH - Rails.application.require_environment! - - Rails.application.load_generators - - require "rails/commands/#{command}" - end - -when 'console' - require 'rails/commands/console' - options = Rails::Console.parse_arguments(ARGV) - - # RAILS_ENV needs to be set before config/application is required - ENV['RAILS_ENV'] = options[:environment] if options[:environment] - - # shift ARGV so IRB doesn't freak - ARGV.shift if ARGV.first && ARGV.first[0] != '-' - - require APP_PATH - Rails.application.require_environment! - Rails::Console.start(Rails.application, options) - -when 'server' - # Change to the application's path if there is no config.ru file in current directory. - # This allows us to run `rails server` from other directories, but still get - # the main config.ru and properly set the tmp directory. - Dir.chdir(File.expand_path('../../', APP_PATH)) unless File.exists?(File.expand_path("config.ru")) - - require 'rails/commands/server' - Rails::Server.new.tap do |server| - # We need to require application after the server sets environment, - # otherwise the --environment option given to the server won't propagate. - require APP_PATH - Dir.chdir(Rails.application.root) - server.start - end - -when 'dbconsole' - require 'rails/commands/dbconsole' - Rails::DBConsole.start - -when 'application', 'runner' - require "rails/commands/#{command}" - -when 'new' - if %w(-h --help).include?(ARGV.first) - require 'rails/commands/application' - else - puts "Can't initialize a new Rails application within the directory of another, please change to a non-Rails directory first.\n" - puts "Type 'rails' for help." - exit(1) - end - -when '--version', '-v' - ARGV.unshift '--version' - require 'rails/commands/application' - -when '-h', '--help' - puts help_message +require 'rails/commands/commands_tasks' -else - puts "Error: Command '#{command}' not recognized" - if %x{rake #{command} --dry-run 2>&1 } && $?.success? - puts "Did you mean: `$ rake #{command}` ?\n\n" - end - puts help_message - exit(1) -end +Rails::CommandsTasks.new(ARGV).run_command!(command) diff --git a/railties/lib/rails/commands/application.rb b/railties/lib/rails/commands/application.rb index 2ff29418c6..c998e6b6a8 100644 --- a/railties/lib/rails/commands/application.rb +++ b/railties/lib/rails/commands/application.rb @@ -1,30 +1,3 @@ -require 'rails/version' - -if ['--version', '-v'].include?(ARGV.first) - puts "Rails #{Rails::VERSION::STRING}" - exit(0) -end - -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' require 'rails/generators/rails/app/app_generator' @@ -40,4 +13,5 @@ module Rails end end -Rails::Generators::AppGenerator.start +args = Rails::Generators::ARGVScrubber.new(ARGV).prepare! +Rails::Generators::AppGenerator.start args diff --git a/railties/lib/rails/commands/commands_tasks.rb b/railties/lib/rails/commands/commands_tasks.rb new file mode 100644 index 0000000000..de60423784 --- /dev/null +++ b/railties/lib/rails/commands/commands_tasks.rb @@ -0,0 +1,174 @@ +module Rails + # This is a class which takes in a rails command and initiates the appropriate + # initiation sequence. + # + # Warning: This class mutates ARGV because some commands require manipulating + # it before they are run. + class CommandsTasks # :nodoc: + attr_reader :argv + + HELP_MESSAGE = <<-EOT +Usage: rails COMMAND [ARGS] + +The most common rails commands are: + generate Generate new code (short-cut alias: "g") + console Start the Rails console (short-cut alias: "c") + server Start the Rails server (short-cut alias: "s") + dbconsole Start a console for the database specified in config/database.yml + (short-cut alias: "db") + new Create a new Rails application. "rails new my_app" creates a + new application called MyApp in "./my_app" + +In addition to those, there are: + application Generate the Rails application code + destroy Undo code generated with "generate" (short-cut alias: "d") + plugin new Generates skeleton for developing a Rails plugin + runner Run a piece of code in the application environment (short-cut alias: "r") + +All commands can be run with -h (or --help) for more information. +EOT + + COMMAND_WHITELIST = %(plugin generate destroy console server dbconsole application runner new version help) + + def initialize(argv) + @argv = argv + end + + def run_command!(command) + command = parse_command(command) + if COMMAND_WHITELIST.include?(command) + send(command) + else + write_error_message(command) + end + end + + def plugin + require_command!("plugin") + end + + def generate + generate_or_destroy(:generate) + end + + def destroy + generate_or_destroy(:destroy) + end + + def console + require_command!("console") + options = Rails::Console.parse_arguments(argv) + + # RAILS_ENV needs to be set before config/application is required + ENV['RAILS_ENV'] = options[:environment] if options[:environment] + + # shift ARGV so IRB doesn't freak + shift_argv! + + require_application_and_environment! + Rails::Console.start(Rails.application, options) + end + + def server + set_application_directory! + require_command!("server") + + Rails::Server.new.tap do |server| + # We need to require application after the server sets environment, + # otherwise the --environment option given to the server won't propagate. + require APP_PATH + Dir.chdir(Rails.application.root) + server.start + end + end + + def dbconsole + require_command!("dbconsole") + Rails::DBConsole.start + end + + def application + require_command!("application") + end + + def runner + require_command!("runner") + end + + def new + if %w(-h --help).include?(argv.first) + require_command!("application") + else + exit_with_initialization_warning! + end + end + + def version + argv.unshift '--version' + require_command!("application") + end + + def help + write_help_message + end + + private + + def exit_with_initialization_warning! + puts "Can't initialize a new Rails application within the directory of another, please change to a non-Rails directory first.\n" + puts "Type 'rails' for help." + exit(1) + end + + def shift_argv! + argv.shift if argv.first && argv.first[0] != '-' + end + + def require_command!(command) + require "rails/commands/#{command}" + end + + def generate_or_destroy(command) + require 'rails/generators' + require_application_and_environment! + Rails.application.load_generators + require "rails/commands/#{command}" + end + + # Change to the application's path if there is no config.ru file in current directory. + # This allows us to run `rails server` from other directories, but still get + # the main config.ru and properly set the tmp directory. + def set_application_directory! + Dir.chdir(File.expand_path('../../', APP_PATH)) unless File.exist?(File.expand_path("config.ru")) + end + + def require_application_and_environment! + require APP_PATH + Rails.application.require_environment! + end + + def write_help_message + puts HELP_MESSAGE + end + + def write_error_message(command) + puts "Error: Command '#{command}' not recognized" + if %x{rake #{command} --dry-run 2>&1 } && $?.success? + puts "Did you mean: `$ rake #{command}` ?\n\n" + end + write_help_message + exit(1) + end + + def parse_command(command) + case command + when '--version', '-v' + 'version' + when '--help', '-h' + 'help' + else + command + end + end + end +end diff --git a/railties/lib/rails/commands/dbconsole.rb b/railties/lib/rails/commands/dbconsole.rb index 5914c9e4ae..f6d8aec30d 100644 --- a/railties/lib/rails/commands/dbconsole.rb +++ b/railties/lib/rails/commands/dbconsole.rb @@ -44,7 +44,7 @@ module Rails find_cmd_and_exec(['mysql', 'mysql5'], *args) - when "postgresql", "postgres" + when "postgresql", "postgres", "postgis" ENV['PGUSER'] = config["username"] if config["username"] ENV['PGHOST'] = config["host"] if config["host"] ENV['PGPORT'] = config["port"].to_s if config["port"] @@ -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 new file mode 100644 index 0000000000..f7a0b99005 --- /dev/null +++ b/railties/lib/rails/commands/plugin.rb @@ -0,0 +1,23 @@ +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' +require 'rails/generators/rails/plugin/plugin_generator' +Rails::Generators::PluginGenerator.start diff --git a/railties/lib/rails/commands/plugin_new.rb b/railties/lib/rails/commands/plugin_new.rb deleted file mode 100644 index 4d7bf3c9f3..0000000000 --- a/railties/lib/rails/commands/plugin_new.rb +++ /dev/null @@ -1,9 +0,0 @@ -if ARGV.first != "new" - ARGV[0] = "--help" -else - ARGV.shift -end - -require 'rails/generators' -require 'rails/generators/rails/plugin_new/plugin_new_generator' -Rails::Generators::PluginNewGenerator.start
\ No newline at end of file diff --git a/railties/lib/rails/commands/runner.rb b/railties/lib/rails/commands/runner.rb index c4622d6a2d..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 @@ -48,7 +57,7 @@ if code_or_file.nil? exit 1 elsif File.exist?(code_or_file) $0 = code_or_file - eval(File.read(code_or_file), nil, code_or_file) + Kernel.load code_or_file else - eval(code_or_file) + eval(code_or_file, binding, __FILE__, __LINE__) end diff --git a/railties/lib/rails/commands/server.rb b/railties/lib/rails/commands/server.rb index e3119ecf22..fec4962fb5 100644 --- a/railties/lib/rails/commands/server.rb +++ b/railties/lib/rails/commands/server.rb @@ -1,6 +1,7 @@ require 'fileutils' require 'optparse' require 'action_dispatch' +require 'rails' module Rails class Server < ::Rack::Server @@ -21,7 +22,7 @@ module Rails opts.on("-e", "--environment=name", String, "Specifies the environment to run this server under (test/development/production).", "Default: development") { |v| options[:environment] = v } - opts.on("-P","--pid=pid",String, + opts.on("-P", "--pid=pid", String, "Specifies the PID file.", "Default: tmp/pids/server.pid") { |v| options[:pid] = v } @@ -32,7 +33,8 @@ module Rails opt_parser.parse! args - options[:server] = args.shift + options[:log_stdout] = options[:daemonize].blank? && (options[:environment] || Rails.env) == "development" + options[:server] = args.shift options end end @@ -59,27 +61,10 @@ module Rails end def start - url = "#{options[:SSLEnable] ? 'https' : 'http'}://#{options[:Host]}:#{options[:Port]}" - puts "=> Booting #{ActiveSupport::Inflector.demodulize(server)}" - puts "=> Rails #{Rails.version} application starting in #{Rails.env} on #{url}" - puts "=> Run `rails server -h` for more startup options" + print_boot_information trap(:INT) { exit } - puts "=> Ctrl-C to shutdown server" unless options[:daemonize] - - #Create required tmp directories if not found - %w(cache pids sessions sockets).each do |dir_to_make| - FileUtils.mkdir_p(File.join(Rails.root, 'tmp', dir_to_make)) - end - - unless options[:daemonize] - wrapped_app # touch the app so the logger is set up - - console = ActiveSupport::Logger.new($stdout) - console.formatter = Rails.logger.formatter - console.level = Rails.logger.level - - Rails.logger.extend(ActiveSupport::Logger.broadcast(console)) - end + create_tmp_directories + log_to_stdout if options[:log_stdout] super ensure @@ -90,7 +75,7 @@ module Rails def middleware middlewares = [] - middlewares << [Rails::Rack::Debugger] if options[:debugger] + middlewares << [Rails::Rack::Debugger] if options[:debugger] middlewares << [::Rack::ContentLength] # FIXME: add Rack::Lock in the case people are using webrick. @@ -110,14 +95,45 @@ module Rails def default_options super.merge({ - Port: 3000, - DoNotReverseLookup: true, - environment: (ENV['RAILS_ENV'] || ENV['RACK_ENV'] || "development").dup, - daemonize: false, - debugger: false, - pid: File.expand_path("tmp/pids/server.pid"), - config: File.expand_path("config.ru") + Port: 3000, + DoNotReverseLookup: true, + environment: (ENV['RAILS_ENV'] || ENV['RACK_ENV'] || "development").dup, + daemonize: false, + debugger: false, + pid: File.expand_path("tmp/pids/server.pid"), + config: File.expand_path("config.ru") }) end + + private + + def print_boot_information + url = "#{options[:SSLEnable] ? 'https' : 'http'}://#{options[:Host]}:#{options[:Port]}" + puts "=> Booting #{ActiveSupport::Inflector.demodulize(server)}" + puts "=> Rails #{Rails.version} application starting in #{Rails.env} on #{url}" + puts "=> Run `rails server -h` for more startup options" + + if options[:Host].to_s.match(/0\.0\.0\.0/) + puts "=> Notice: server is listening on all interfaces (#{options[:Host]}). Consider using 127.0.0.1 (--binding option)" + end + + puts "=> Ctrl-C to shutdown server" unless options[:daemonize] + end + + def create_tmp_directories + %w(cache pids sessions sockets).each do |dir_to_make| + FileUtils.mkdir_p(File.join(Rails.root, 'tmp', dir_to_make)) + end + end + + def log_to_stdout + wrapped_app # touch the app so the logger is set up + + console = ActiveSupport::Logger.new($stdout) + console.formatter = Rails.logger.formatter + console.level = Rails.logger.level + + Rails.logger.extend(ActiveSupport::Logger.broadcast(console)) + end end end diff --git a/railties/lib/rails/configuration.rb b/railties/lib/rails/configuration.rb index 15d13d5f28..f5d7dede66 100644 --- a/railties/lib/rails/configuration.rb +++ b/railties/lib/rails/configuration.rb @@ -1,4 +1,3 @@ -require 'active_support/deprecation' require 'active_support/ordered_options' require 'active_support/core_ext/object' require 'rails/paths' @@ -60,6 +59,10 @@ module Rails @operations << [__method__, args, block] end + def unshift(*args, &block) + @operations << [__method__, args, block] + end + def merge_into(other) #:nodoc: @operations.each do |operation, args, block| other.send(operation, *args, &block) diff --git a/railties/lib/rails/console/helpers.rb b/railties/lib/rails/console/helpers.rb index 230d3d9d04..b775f1ff8d 100644 --- a/railties/lib/rails/console/helpers.rb +++ b/railties/lib/rails/console/helpers.rb @@ -1,9 +1,15 @@ module Rails module ConsoleMethods + # Gets the helper methods available to the controller. + # + # This method assumes an +ApplicationController+ exists, and it extends +ActionController::Base+ def helper @helper ||= ApplicationController.helpers end + # Gets a new instance of a controller object. + # + # This method assumes an +ApplicationController+ exists, and it extends +ActionController::Base+ def controller @controller ||= ApplicationController.new end diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb index 8000fc3b1e..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 @@ -102,7 +101,7 @@ module Rails # paths["config"] # => ["config"] # paths["config/initializers"] # => ["config/initializers"] # paths["config/locales"] # => ["config/locales"] - # paths["config/routes"] # => ["config/routes.rb"] + # paths["config/routes.rb"] # => ["config/routes.rb"] # end # # The <tt>Application</tt> class adds a couple more paths to this set. And as in your @@ -260,7 +259,7 @@ module Rails # # class FooController < ApplicationController # def index - # my_engine.root_url #=> /my_engine/ + # my_engine.root_url # => /my_engine/ # end # end # @@ -269,7 +268,7 @@ module Rails # module MyEngine # class BarController # def index - # main_app.foo_path #=> /foo + # main_app.foo_path # => /foo # end # end # end @@ -351,8 +350,13 @@ module Rails Rails::Railtie::Configuration.eager_load_namespaces << base base.called_from = begin - # Remove the line number from backtraces making sure we don't leave anything behind - call_stack = caller.map { |p| p.sub(/:\d+.*/, '') } + call_stack = if Kernel.respond_to?(:caller_locations) + caller_locations.map(&:path) + else + # Remove the line number from backtraces making sure we don't leave anything behind + caller.map { |p| p.sub(/:\d+.*/, '') } + end + File.dirname(call_stack.detect { |p| p !~ %r[railties[\w.-]*/lib/rails|rack[\w.-]*/lib/rack] }) end end @@ -460,7 +464,7 @@ module Rails # files inside eager_load paths. def eager_load! config.eager_load_paths.each do |load_path| - matcher = /\A#{Regexp.escape(load_path)}\/(.*)\.rb\Z/ + matcher = /\A#{Regexp.escape(load_path.to_s)}\/(.*)\.rb\Z/ Dir.glob("#{load_path}/**/*.rb").sort.each do |file| require_dependency file.sub(matcher, '\1') end @@ -606,7 +610,7 @@ module Rails initializer :load_config_initializers do config.paths["config/initializers"].existent.sort.each do |initializer| - load(initializer) + load_config_initializer(initializer) end end @@ -640,6 +644,12 @@ module Rails protected + def load_config_initializer(initializer) + ActiveSupport::Notifications.instrument('load_config_initializer.railties', initializer: initializer) do + load(initializer) + end + end + def run_tasks_blocks(*) #:nodoc: super paths["lib/tasks"].existent.sort.each { |ext| load(ext) } diff --git a/railties/lib/rails/engine/railties.rb b/railties/lib/rails/engine/railties.rb index 1081700cd0..9969a1475d 100644 --- a/railties/lib/rails/engine/railties.rb +++ b/railties/lib/rails/engine/railties.rb @@ -9,10 +9,6 @@ module Rails ::Rails::Engine.subclasses.map(&:instance) end - def self.engines - @engines ||= ::Rails::Engine.subclasses.map(&:instance) - end - def each(*args, &block) _all.each(*args, &block) end @@ -20,10 +16,6 @@ module Rails def -(others) _all - others end - - delegate :engines, to: "self.class" end end end - -ActiveSupport::Deprecation.deprecate_methods(Rails::Engine::Railties, :engines) diff --git a/railties/lib/rails/generators.rb b/railties/lib/rails/generators.rb index 4b767ea0c6..dce734b54e 100644 --- a/railties/lib/rails/generators.rb +++ b/railties/lib/rails/generators.rb @@ -1,6 +1,8 @@ activesupport_path = File.expand_path('../../../../activesupport/lib', __FILE__) $:.unshift(activesupport_path) if File.directory?(activesupport_path) && !$:.include?(activesupport_path) +require 'thor/group' + require 'active_support' require 'active_support/core_ext/object/blank' require 'active_support/core_ext/kernel/singleton_class' @@ -9,12 +11,11 @@ require 'active_support/core_ext/hash/deep_merge' require 'active_support/core_ext/module/attribute_accessors' require 'active_support/core_ext/string/inflections' -require 'rails/generators/base' - module Rails module Generators autoload :Actions, 'rails/generators/actions' autoload :ActiveModel, 'rails/generators/active_model' + autoload :Base, 'rails/generators/base' autoload :Migration, 'rails/generators/migration' autoload :NamedBase, 'rails/generators/named_base' autoload :ResourceHelpers, 'rails/generators/resource_helpers' @@ -225,7 +226,7 @@ module Rails rails = groups.delete("rails") rails.map! { |n| n.sub(/^rails:/, '') } rails.delete("app") - rails.delete("plugin_new") + rails.delete("plugin") print_list("rails", rails) hidden_namespaces.each { |n| groups.delete(n.to_s) } 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/active_model.rb b/railties/lib/rails/generators/active_model.rb index e5373704d7..6183944bb0 100644 --- a/railties/lib/rails/generators/active_model.rb +++ b/railties/lib/rails/generators/active_model.rb @@ -1,5 +1,3 @@ -require 'active_support/deprecation' - module Rails module Generators # ActiveModel is a class to be implemented by each ORM to allow Rails to @@ -65,12 +63,6 @@ module Rails "#{name}.update(#{params})" end - def update_attributes(*args) # :nodoc: - ActiveSupport::Deprecation.warn("Calling '@orm_instance.update_attributes' " \ - "is deprecated, please use '@orm_instance.update' instead.") - update(*args) - end - # POST create # PATCH/PUT update def errors diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb index 675ada7ed0..4988602aea 100644 --- a/railties/lib/rails/generators/app_base.rb +++ b/railties/lib/rails/generators/app_base.rb @@ -1,10 +1,10 @@ require 'digest/md5' -require 'securerandom' require 'active_support/core_ext/string/strip' require 'rails/version' unless defined?(Rails::VERSION) -require 'rbconfig' require 'open-uri' require 'uri' +require 'rails/generators' +require 'active_support/core_ext/array/extract_options' module Rails module Generators @@ -14,14 +14,22 @@ module Rails DATABASES.concat(JDBC_DATABASES) attr_accessor :rails_template + attr_accessor :app_template add_shebang_option! argument :app_path, type: :string + def self.strict_args_position + false + end + def self.add_shared_options_for(name) class_option :template, type: :string, aliases: '-m', desc: "Path to some #{name} template (can be a filesystem path or URL)" + class_option :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" @@ -37,9 +45,15 @@ module Rails class_option :skip_active_record, type: :boolean, aliases: '-O', default: false, desc: 'Skip Active Record files' + class_option :skip_action_view, type: :boolean, aliases: '-V', default: false, + desc: 'Skip Action View files' + class_option :skip_sprockets, type: :boolean, aliases: '-S', default: false, desc: 'Skip Sprockets files' + class_option :skip_spring, type: :boolean, default: false, + desc: "Don't install Spring application preloader" + class_option :database, type: :string, aliases: '-d', default: 'sqlite3', desc: "Preconfigure for selected database (options: #{DATABASES.join('/')})" @@ -69,13 +83,53 @@ module Rails end def initialize(*args) - @original_wd = Dir.pwd + @original_wd = Dir.pwd + @gem_filter = lambda { |gem| true } + @extra_entries = [] super convert_database_option_for_jruby end protected + def gemfile_entry(name, *args) + options = args.extract_options! + version = args.first + github = options[:github] + path = options[:path] + + if github + @extra_entries << GemfileEntry.github(name, github) + elsif path + @extra_entries << GemfileEntry.path(name, path) + else + @extra_entries << GemfileEntry.version(name, version) + end + self + end + + def gemfile_entries + [ rails_gemfile_entry, + database_gemfile_entry, + assets_gemfile_entry, + javascript_gemfile_entry, + jbuilder_gemfile_entry, + sdoc_gemfile_entry, + platform_dependent_gemfile_entry, + spring_gemfile_entry, + @extra_entries].flatten.find_all(&@gem_filter) + end + + def add_gem_entry_filter + @gem_filter = lambda { |next_filter, entry| + yield(entry) && next_filter.call(entry) + }.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 @@ -89,63 +143,148 @@ module Rails end def create_root - self.destination_root = File.expand_path(app_path, destination_root) valid_const? empty_directory '.' - set_default_accessors! FileUtils.cd(destination_root) unless options[:pretend] end + class TemplateRecorder < ::BasicObject # :nodoc: + attr_reader :gems + + def initialize(target) + @target = target + # unfortunately, instance eval has access to these ivars + @app_const = target.send :app_const if target.respond_to?(:app_const, true) + @app_const_base = target.send :app_const_base if target.respond_to?(:app_const_base, true) + @app_name = target.send :app_name if target.respond_to?(:app_name, true) + @commands = [] + @gems = [] + end + + def gemfile_entry(*args) + @target.send :gemfile_entry, *args + end + + def add_gem_entry_filter(*args, &block) + @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 + + def respond_to_missing?(method, priv = false) + super || @target.respond_to?(method, priv) + end + + def replay! + @commands.each do |name, args, block| + @target.send name, *args, &block + end + end + end + def apply_rails_template - apply rails_template if rails_template + @recorder = TemplateRecorder.new self + + 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 + def replay_template + @recorder.replay! if @recorder + end + + def apply(path, config={}) + verbose = config.fetch(:verbose, true) + target = config.fetch(:target, self) + is_uri = path =~ /^https?\:\/\// + path = find_in_source_paths(path) unless is_uri + + say_status :apply, path, verbose + shell.padding += 1 if verbose + + if is_uri + contents = open(path, "Accept" => "application/x-thor-template") {|io| io.read } + else + contents = open(path) {|io| io.read } + end + + target.instance_eval(contents, path) + shell.padding -= 1 if verbose + end + def set_default_accessors! - self.rails_template = case options[:template] - when /^https?:\/\// - options[:template] - when String - File.expand_path(options[:template], Dir.pwd) - else - options[:template] + self.destination_root = File.expand_path(app_path, destination_root) + 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 def database_gemfile_entry - options[:skip_active_record] ? "" : - <<-GEMFILE.strip_heredoc - # Use #{options[:database]} as the database for Active Record - gem '#{gem_for_database}' - GEMFILE + return [] if options[:skip_active_record] + GemfileEntry.version gem_for_database, nil, + "Use #{options[:database]} as the database for Active Record" end def include_all_railties? - !options[:skip_active_record] && !options[:skip_test_unit] && !options[:skip_sprockets] + !options[:skip_active_record] && !options[:skip_action_view] && !options[:skip_test_unit] && !options[:skip_sprockets] end def comment_if(value) options[value] ? '# ' : '' end + class GemfileEntry < Struct.new(:name, :version, :comment, :options, :commented_out) + def initialize(name, version, comment, options = {}, commented_out = false) + super + end + + def self.github(name, github, comment = nil) + new(name, nil, comment, github: github) + end + + def self.version(name, version, comment = nil) + new(name, version, comment) + end + + def self.path(name, path, comment = nil) + new(name, nil, comment, path: path) + end + + def padding(max_width) + ' ' * (max_width - name.length + 2) + end + end + def rails_gemfile_entry if options.dev? - <<-GEMFILE.strip_heredoc - gem 'rails', path: '#{Rails::Generators::RAILS_DEV_PATH}' - gem 'arel', github: 'rails/arel' - GEMFILE + [GemfileEntry.path('rails', Rails::Generators::RAILS_DEV_PATH), + GemfileEntry.github('arel', 'rails/arel')] elsif options.edge? - <<-GEMFILE.strip_heredoc - gem 'rails', github: 'rails/rails' - gem 'arel', github: 'rails/arel' - GEMFILE + [GemfileEntry.github('rails', 'rails/rails'), + GemfileEntry.github('arel', 'rails/arel')] else - <<-GEMFILE.strip_heredoc - # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' - gem 'rails', '#{Rails::VERSION::STRING}' - GEMFILE + [GemfileEntry.version('rails', + Rails::VERSION::STRING, + "Bundle edge Rails instead: gem 'rails', github: 'rails/rails'")] end end @@ -177,77 +316,81 @@ module Rails end def assets_gemfile_entry - return if options[:skip_sprockets] - - gemfile = if options.dev? || options.edge? - <<-GEMFILE.strip_heredoc - # Use edge version of sprockets-rails - gem 'sprockets-rails', github: 'rails/sprockets-rails' + return [] if options[:skip_sprockets] - # Use SCSS for stylesheets - gem 'sass-rails', github: 'rails/sass-rails' - GEMFILE + gems = [] + if options.dev? || options.edge? + gems << GemfileEntry.github('sprockets-rails', 'rails/sprockets-rails', + 'Use edge version of sprockets-rails') + gems << GemfileEntry.github('sass-rails', 'rails/sass-rails', + 'Use SCSS for stylesheets') else - <<-GEMFILE.strip_heredoc - # Use SCSS for stylesheets - gem 'sass-rails', '~> 4.0.0.rc1' - GEMFILE + gems << GemfileEntry.version('sass-rails', + '~> 4.0.1', + 'Use SCSS for stylesheets') end - gemfile += <<-GEMFILE.strip_heredoc + gems << GemfileEntry.version('uglifier', + '>= 1.3.0', + 'Use Uglifier as compressor for JavaScript assets') - # Use Uglifier as compressor for JavaScript assets - gem 'uglifier', '>= 1.3.0' - GEMFILE + gems + end - if options[:skip_javascript] - gemfile += <<-GEMFILE - #{coffee_gemfile_entry} - #{javascript_runtime_gemfile_entry} - GEMFILE + def platform_dependent_gemfile_entry + gems = [] + if RUBY_ENGINE == 'rbx' + gems << GemfileEntry.version('rubysl', nil) end + gems + end + + def jbuilder_gemfile_entry + comment = 'Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder' + GemfileEntry.version('jbuilder', '~> 2.0', comment) + end - gemfile.gsub(/^[ \t]+/, '') + def sdoc_gemfile_entry + comment = 'bundle exec rake doc:rails generates the API under doc/api.' + GemfileEntry.new('sdoc', nil, comment, { group: :doc, require: false }) end def coffee_gemfile_entry + comment = 'Use CoffeeScript for .js.coffee assets and views' if options.dev? || options.edge? - <<-GEMFILE - # Use CoffeeScript for .js.coffee assets and views - gem 'coffee-rails', github: 'rails/coffee-rails' - GEMFILE + GemfileEntry.github 'coffee-rails', 'rails/coffee-rails', comment else - <<-GEMFILE - # Use CoffeeScript for .js.coffee assets and views - gem 'coffee-rails', '~> 4.0.0' - GEMFILE + GemfileEntry.version 'coffee-rails', '~> 4.0.0', comment end end def javascript_gemfile_entry - unless options[:skip_javascript] - <<-GEMFILE.gsub(/^[ \t]+/, '') - #{coffee_gemfile_entry} - #{javascript_runtime_gemfile_entry} - # Use #{options[:javascript]} as the JavaScript library - gem '#{options[:javascript]}-rails' - - # Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks - gem 'turbolinks' - GEMFILE + if options[:skip_javascript] + [] + else + gems = [coffee_gemfile_entry, javascript_runtime_gemfile_entry] + gems << GemfileEntry.version("#{options[:javascript]}-rails", nil, + "Use #{options[:javascript]} as the JavaScript library") + + gems << GemfileEntry.version("turbolinks", nil, + "Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks") + gems end end def javascript_runtime_gemfile_entry - runtime = if defined?(JRUBY_VERSION) - "gem 'therubyrhino'" + comment = 'See https://github.com/sstephenson/execjs#readme for more supported runtimes' + if defined?(JRUBY_VERSION) + GemfileEntry.version 'therubyrhino', nil, comment else - "# gem 'therubyracer', platforms: :ruby" + GemfileEntry.new 'therubyracer', nil, comment, { platforms: :ruby }, true end - <<-GEMFILE - # See https://github.com/sstephenson/execjs#readme for more supported runtimes - #{runtime} - GEMFILE + 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) @@ -273,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 7e938fab47..67bab96a22 100644 --- a/railties/lib/rails/generators/base.rb +++ b/railties/lib/rails/generators/base.rb @@ -7,8 +7,6 @@ rescue LoadError exit end -require 'rails/generators/actions' - module Rails module Generators class Error < Thor::Error # :nodoc: @@ -168,15 +166,15 @@ module Rails as_hook = options.delete(:as) || generator_name names.each do |name| - defaults = if options[:type] == :boolean - { } - elsif [true, false].include?(default_value_for_option(name, options)) - { banner: "" } - else - { desc: "#{name.to_s.humanize} to be invoked", banner: "NAME" } - end - unless class_options.key?(name) + defaults = if options[:type] == :boolean + { } + elsif [true, false].include?(default_value_for_option(name, options)) + { banner: "" } + else + { desc: "#{name.to_s.humanize} to be invoked", banner: "NAME" } + end + class_option(name, defaults.merge!(options)) end @@ -211,7 +209,7 @@ module Rails return unless base_name && generator_name return unless default_generator_root path = File.join(default_generator_root, 'templates') - path if File.exists?(path) + path if File.exist?(path) end # Returns the base root for a common set of generators. This is used to dynamically @@ -255,12 +253,7 @@ module Rails # Split the class from its module nesting nesting = class_name.split('::') last_name = nesting.pop - - # Extract the last Module in the nesting - last = nesting.inject(Object) do |last_module, nest| - break unless last_module.const_defined?(nest, false) - last_module.const_get(nest) - end + last = extract_last_module(nesting) if last && last.const_defined?(last_name.camelize, false) raise Error, "The name '#{class_name}' is either already used in your application " << @@ -270,6 +263,14 @@ module Rails end end + # Takes in an array of nested modules and extracts the last module + def extract_last_module(nesting) + nesting.inject(Object) do |last_module, nest| + break unless last_module.const_defined?(nest, false) + last_module.const_get(nest) + end + end + # Use Rails default banner. def self.banner "rails generate #{namespace.sub(/^rails:/,'')} #{self.arguments.map{ |a| a.usage }.join(' ')} [options]".gsub(/\s+/, ' ') @@ -295,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]) @@ -365,12 +366,12 @@ module Rails source_root && File.expand_path("../USAGE", source_root), default_generator_root && File.join(default_generator_root, "USAGE") ] - paths.compact.detect { |path| File.exists? path } + paths.compact.detect { |path| File.exist? path } end def self.default_generator_root path = File.expand_path(File.join(base_name, generator_name), base_root) - path if File.exists?(path) + path if File.exist?(path) end end 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/erb/scaffold/templates/_form.html.erb b/railties/lib/rails/generators/erb/scaffold/templates/_form.html.erb index 1799e823b6..69c10efa47 100644 --- a/railties/lib/rails/generators/erb/scaffold/templates/_form.html.erb +++ b/railties/lib/rails/generators/erb/scaffold/templates/_form.html.erb @@ -21,8 +21,13 @@ <%%= f.label :password_confirmation %><br> <%%= f.password_field :password_confirmation %> <% else -%> + <%- if attribute.reference? -%> + <%%= f.label :<%= attribute.column_name %> %><br> + <%%= f.<%= attribute.field_type %> :<%= attribute.column_name %> %> + <%- else -%> <%%= f.label :<%= attribute.name %> %><br> <%%= f.<%= attribute.field_type %> :<%= attribute.name %> %> + <%- end -%> <% end -%> </div> <% end -%> diff --git a/railties/lib/rails/generators/erb/scaffold/templates/index.html.erb b/railties/lib/rails/generators/erb/scaffold/templates/index.html.erb index 9d778642f2..814d6fdb0e 100644 --- a/railties/lib/rails/generators/erb/scaffold/templates/index.html.erb +++ b/railties/lib/rails/generators/erb/scaffold/templates/index.html.erb @@ -6,9 +6,7 @@ <% attributes.reject(&:password_digest?).each do |attribute| -%> <th><%= attribute.human_name %></th> <% end -%> - <th></th> - <th></th> - <th></th> + <th colspan="3"></th> </tr> </thead> diff --git a/railties/lib/rails/generators/migration.rb b/railties/lib/rails/generators/migration.rb index cd69a017dd..3566f96f5e 100644 --- a/railties/lib/rails/generators/migration.rb +++ b/railties/lib/rails/generators/migration.rb @@ -1,15 +1,14 @@ +require 'active_support/concern' + module Rails module Generators # Holds common methods for migrations. It assumes that migrations has the # [0-9]*_name format and can be used by another frameworks (like Sequel) # just by implementing the next migration version method. module Migration + extend ActiveSupport::Concern attr_reader :migration_number, :migration_file_name, :migration_class_name - def self.included(base) #:nodoc: - base.extend ClassMethods - end - module ClassMethods def migration_lookup_at(dirname) #:nodoc: Dir.glob("#{dirname}/[0-9]*_*.rb") diff --git a/railties/lib/rails/generators/named_base.rb b/railties/lib/rails/generators/named_base.rb index e712c747b0..5a92ab3e95 100644 --- a/railties/lib/rails/generators/named_base.rb +++ b/railties/lib/rails/generators/named_base.rb @@ -90,7 +90,7 @@ module Rails end def namespaced_path - @namespaced_path ||= namespace.name.split("::").map {|m| m.underscore }[0] + @namespaced_path ||= namespace.name.split("::").first.underscore end def class_name diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index d48dcf9ef3..d2eca5b2fb 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -68,7 +68,7 @@ module Rails directory "bin" do |content| "#{shebang}\n" + content end - chmod "bin", 0755, verbose: false + chmod "bin", 0755 & ~File.umask, verbose: false end def config @@ -78,6 +78,7 @@ module Rails template "routes.rb" template "application.rb" template "environment.rb" + template "secrets.yml" directory "environments" directory "initializers" @@ -129,7 +130,9 @@ module Rails end def vendor_javascripts - empty_directory_with_keep_file 'vendor/assets/javascripts' + unless options[:skip_javascript] + empty_directory_with_keep_file 'vendor/assets/javascripts' + end end def vendor_stylesheets @@ -151,23 +154,19 @@ module Rails desc: "Show Rails version number and quit" def initialize(*args) - if args[0].blank? - if args[1].blank? - # rails new - raise Error, "Application name should be provided in arguments. For details run: rails --help" - else - # rails new --skip-bundle my_new_application - raise Error, "Options should be given after the application name. For details run: rails --help" - end - end - super + unless app_path + raise Error, "Application name should be provided in arguments. For details run: rails --help" + end + if !options[:skip_active_record] && !DATABASES.include?(options[:database]) raise Error, "Invalid value for --database option. Supported for preconfiguration are: #{DATABASES.join(", ")}." end end + public_task :set_default_accessors! + public_task :apply_rails_template public_task :create_root def create_root_files @@ -227,11 +226,19 @@ module Rails build(:vendor) 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 :apply_rails_template, :run_bundle + public_task :run_bundle + public_task :replay_template + public_task :generate_spring_binstubs protected @@ -245,7 +252,7 @@ module Rails end def app_name - @app_name ||= (defined_app_const_base? ? defined_app_name : File.basename(destination_root)).tr(".", "_") + @app_name ||= (defined_app_const_base? ? defined_app_name : File.basename(destination_root)).tr('\\', '').tr(". ", "_") end def defined_app_name @@ -300,5 +307,76 @@ module Rails defined?(::AppBuilder) ? ::AppBuilder : Rails::AppBuilder end end + + # This class handles preparation of the arguments before the AppGenerator is + # called. The class provides version or help information if they were + # requested, and also constructs the railsrc file (used for extra configuration + # options). + # + # This class should be called before the AppGenerator is required and started + # since it configures and mutates ARGV correctly. + class ARGVScrubber # :nodoc + def initialize(argv = ARGV) + @argv = argv + end + + def prepare! + handle_version_request!(@argv.first) + handle_invalid_command!(@argv.first, @argv) do + handle_rails_rc!(@argv.drop(1)) + end + end + + def self.default_rc_file + File.expand_path('~/.railsrc') + end + + private + + def handle_version_request!(argument) + if ['--version', '-v'].include?(argument) + require 'rails/version' + puts "Rails #{Rails::VERSION::STRING}" + exit(0) + end + end + + def handle_invalid_command!(argument, argv) + if argument == "new" + yield + else + ['--help'] + argv.drop(1) + end + end + + def handle_rails_rc!(argv) + if argv.find { |arg| arg == '--no-rc' } + argv.reject { |arg| arg == '--no-rc' } + else + railsrc(argv) { |rc_argv, rc| insert_railsrc_into_argv!(rc_argv, rc) } + end + end + + def railsrc(argv) + if (customrc = argv.index{ |x| x.include?("--rc=") }) + fname = File.expand_path(argv[customrc].gsub(/--rc=/, "")) + yield(argv.take(customrc) + argv.drop(customrc + 1), fname) + else + yield argv, self.class.default_rc_file + end + end + + def read_rc_file(railsrc) + extra_args = File.readlines(railsrc).flat_map(&:split) + puts "Using #{extra_args.join(" ")} from #{railsrc}" + extra_args + end + + def insert_railsrc_into_argv!(argv, railsrc) + return argv unless File.exist?(railsrc) + extra_args = read_rc_file railsrc + argv.take(1) + extra_args + argv.drop(1) + end + end end end diff --git a/railties/lib/rails/generators/rails/app/templates/Gemfile b/railties/lib/rails/generators/rails/app/templates/Gemfile index 577ff651e5..68bd62d4b1 100644 --- a/railties/lib/rails/generators/rails/app/templates/Gemfile +++ b/railties/lib/rails/generators/rails/app/templates/Gemfile @@ -1,30 +1,35 @@ source 'https://rubygems.org' -<%= rails_gemfile_entry -%> +<% max_width = gemfile_entries.map { |g| g.name.length }.max -%> +<% gemfile_entries.each do |gem| -%> +<% if gem.comment -%> -<%= database_gemfile_entry -%> - -<%= assets_gemfile_entry %> -<%= javascript_gemfile_entry -%> - -# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder -gem 'jbuilder', '~> 1.2' - -group :doc do - # bundle exec rake doc:rails generates the API under doc/api. - gem 'sdoc', require: false -end +# <%= gem.comment %> +<% end -%> +<%= gem.commented_out ? '# ' : '' %>gem '<%= gem.name %>'<% if gem.version -%> +, '<%= gem.version %>' +<% elsif gem.options.any? -%> +,<%= gem.padding(max_width) %><%= gem.options.map { |k,v| + "#{k}: #{v.inspect}" }.join(', ') %> +<% else %> +<% end -%> +<% end -%> # Use ActiveModel has_secure_password -# gem 'bcrypt-ruby', '~> 3.0.0' +# gem 'bcrypt-ruby', '~> 3.1.2' # Use unicorn as the app server # gem 'unicorn' # Use Capistrano for deployment -# gem 'capistrano', group: :development +# gem 'capistrano-rails', group: :development <% unless defined?(JRUBY_VERSION) -%> # Use debugger # gem 'debugger', group: [:development, :test] <% end -%> + +<% if RUBY_PLATFORM.match(/bccwin|cygwin|emx|mingw|mswin|wince/) -%> +# Windows does not include zoneinfo files, so bundle the tzinfo-data gem +gem 'tzinfo-data', platforms: [:mingw, :mswin] +<% end -%> diff --git a/railties/lib/rails/generators/rails/app/templates/app/assets/javascripts/application.js.tt b/railties/lib/rails/generators/rails/app/templates/app/assets/javascripts/application.js.tt index 6899dfe9c9..07ea09cdbd 100644 --- a/railties/lib/rails/generators/rails/app/templates/app/assets/javascripts/application.js.tt +++ b/railties/lib/rails/generators/rails/app/templates/app/assets/javascripts/application.js.tt @@ -7,11 +7,14 @@ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the // compiled file. // -// stub path allows dependency to be excluded from the asset bundle. +// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details +// about supported directives. // <% unless options[:skip_javascript] -%> //= require <%= options[:javascript] %> //= require <%= options[:javascript] %>_ujs +<% if gemfile_entries.any? { |m| m.name == "turbolinks" } -%> //= require turbolinks <% end -%> +<% end -%> //= require_tree . diff --git a/railties/lib/rails/generators/rails/app/templates/app/assets/stylesheets/application.css b/railties/lib/rails/generators/rails/app/templates/app/assets/stylesheets/application.css index 3192ec897b..a443db3401 100644 --- a/railties/lib/rails/generators/rails/app/templates/app/assets/stylesheets/application.css +++ b/railties/lib/rails/generators/rails/app/templates/app/assets/stylesheets/application.css @@ -5,9 +5,11 @@ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path. * - * You're free to add application-wide styles to this file and they'll appear at the top of the - * compiled file, but it's generally better to create a new file per style scope. + * You're free to add application-wide styles to this file and they'll appear at the bottom of the + * compiled file so the styles you add here take precedence over styles defined in any styles + * defined in the other CSS/SCSS files in this directory. It is generally better to create a new + * file per style scope. * - *= require_self *= require_tree . + *= require_self */ diff --git a/railties/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt b/railties/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt index d87c7b7268..fe71f7122c 100644 --- a/railties/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt +++ b/railties/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt @@ -2,8 +2,17 @@ <html> <head> <title><%= camelized %></title> + <%- if options[:skip_javascript] -%> + <%%= stylesheet_link_tag "application", media: "all" %> + <%- else -%> + <%- if gemfile_entries.any? { |m| m.name == "turbolinks" } -%> <%%= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true %> <%%= javascript_include_tag "application", "data-turbolinks-track" => true %> + <%- else -%> + <%%= stylesheet_link_tag "application", media: "all" %> + <%%= javascript_include_tag "application" %> + <%- end -%> + <%- end -%> <%%= csrf_meta_tags %> </head> <body> 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 ceb2bdf371..16fe50bab8 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/application.rb +++ b/railties/lib/rails/generators/rails/app/templates/config/application.rb @@ -4,16 +4,18 @@ require File.expand_path('../boot', __FILE__) require 'rails/all' <% else -%> # Pick the frameworks you want: +require "active_model/railtie" <%= comment_if :skip_active_record %>require "active_record/railtie" require "action_controller/railtie" require "action_mailer/railtie" +<%= comment_if :skip_action_view %>require "action_view/railtie" <%= comment_if :skip_sprockets %>require "sprockets/railtie" <%= comment_if :skip_test_unit %>require "rails/test_unit/railtie" <% end -%> # 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 @@ -28,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/boot.rb b/railties/lib/rails/generators/rails/app/templates/config/boot.rb index 3596736667..5e5f0c1fac 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/boot.rb +++ b/railties/lib/rails/generators/rails/app/templates/config/boot.rb @@ -1,4 +1,4 @@ # Set up gems listed in the Gemfile. ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) -require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE']) +require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE']) 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 4807986333..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 @@ -6,26 +6,24 @@ # Configure Using Gemfile # gem 'ruby-frontbase' # -development: +default: &default adapter: frontbase host: localhost - database: <%= app_name %>_development username: <%= app_name %> password: '' +development: + <<: *default + database: <%= app_name %>_development + # Warning: The database defined as "test" will be erased and # re-generated from your development database when you run "rake". # Do not set this db to the same as development or production. test: - adapter: frontbase - host: localhost + <<: *default database: <%= app_name %>_test - username: <%= app_name %> - password: '' +# Do not keep production credentials in the repository, +# instead read the configuration from the environment. production: - adapter: frontbase - host: localhost - database: <%= app_name %>_production - username: <%= app_name %> - password: '' + 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 3d689a110a..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 @@ -33,12 +33,11 @@ # # For more details on the installation and the connection parameters below, # please refer to the latest documents at http://rubyforge.org/docman/?group_id=2361 - -development: +# +default: &default adapter: ibm_db username: db2inst1 password: - database: <%= app_name[0,4] %>_dev #schema: db2inst1 #host: localhost #port: 50000 @@ -51,36 +50,18 @@ development: #authentication: SERVER #parameterized: false +development: + <<: *default + database: <%= app_name[0,4] %>_dev + +# Warning: The database defined as "test" will be erased and +# re-generated from your development database when you run "rake". +# Do not set this db to the same as development or production. test: - adapter: ibm_db - username: db2inst1 - password: + <<: *default database: <%= app_name[0,4] %>_tst - #schema: db2inst1 - #host: localhost - #port: 50000 - #account: my_account - #app_user: my_app_user - #application: my_application - #workstation: my_workstation - #security: SSL - #timeout: 10 - #authentication: SERVER - #parameterized: false +# Do not keep production credentials in the repository, +# instead read the configuration from the environment. production: - adapter: ibm_db - username: db2inst1 - password: - database: <%= app_name[0,8] %> - #schema: db2inst1 - #host: localhost - #port: 50000 - #account: my_account - #app_user: my_app_user - #application: my_application - #workstation: my_workstation - #security: SSL - #timeout: 10 - #authentication: SERVER - #parameterized: false
\ No newline at end of file + 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 1d2bf08b91..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 @@ -5,58 +5,55 @@ # Configure using Gemfile: # gem 'activerecord-jdbcmssql-adapter' # -#development: -# adapter: mssql -# username: <%= app_name %> -# password: -# host: localhost -# database: <%= app_name %>_development +# development: +# adapter: mssql +# username: <%= app_name %> +# password: +# host: localhost +# database: <%= app_name %>_development # # Warning: The database defined as "test" will be erased and # re-generated from your development database when you run "rake". # Do not set this db to the same as development or production. # -#test: -# adapter: mssql -# username: <%= app_name %> -# password: -# host: localhost -# database: <%= app_name %>_test +# test: +# adapter: mssql +# username: <%= app_name %> +# password: +# host: localhost +# database: <%= app_name %>_test # -#production: -# adapter: mssql -# username: <%= app_name %> -# password: -# host: localhost -# database: <%= app_name %>_production +# production: +# adapter: mssql +# username: <%= app_name %> +# password: +# host: localhost +# database: <%= app_name %>_production # If you are using oracle, db2, sybase, informix or prefer to use the plain # JDBC adapter, configure your database setting as the example below (requires # you to download and manually install the database vendor's JDBC driver .jar -# file). See your driver documentation for the apropriate driver class and +# file). See your driver documentation for the appropriate driver class and # connection string: -development: +default: &default adapter: jdbc username: <%= app_name %> password: driver: + +development: + <<: *default url: jdbc:db://localhost/<%= app_name %>_development # Warning: The database defined as "test" will be erased and # re-generated from your development database when you run "rake". # Do not set this db to the same as development or production. - test: - adapter: jdbc - username: <%= app_name %> - password: - driver: + <<: *default url: jdbc:db://localhost/<%= app_name %>_test +# Do not keep production credentials in the repository, +# instead read the configuration from the environment. production: - adapter: jdbc - username: <%= app_name %> - password: - driver: - 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 5a594ac1f3..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 @@ -8,26 +8,24 @@ # # And be sure to use new-style password hashing: # http://dev.mysql.com/doc/refman/5.0/en/old-client.html -development: +# +default: &default adapter: mysql - database: <%= app_name %>_development username: root password: host: localhost +development: + <<: *default + database: <%= app_name %>_development + # Warning: The database defined as "test" will be erased and # re-generated from your development database when you run "rake". # Do not set this db to the same as development or production. test: - adapter: mysql + <<: *default database: <%= app_name %>_test - username: root - password: - host: localhost -production: - adapter: mysql - database: <%= app_name %>_production - username: root - password: - host: localhost +# 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 e1a00d076f..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 @@ -2,13 +2,23 @@ # # Configure Using Gemfile # gem 'activerecord-jdbcpostgresql-adapter' - -development: +# +default: &default adapter: postgresql encoding: unicode + +development: + <<: *default database: <%= app_name %>_development - username: <%= app_name %> - password: + + # 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 @@ -29,15 +39,10 @@ development: # re-generated from your development database when you run "rake". # Do not set this db to the same as development or production. test: - adapter: postgresql - encoding: unicode + <<: *default database: <%= app_name %>_test - username: <%= app_name %> - password: +# Do not keep production credentials in the repository, +# instead read the configuration from the environment. production: - adapter: postgresql - encoding: unicode - database: <%= app_name %>_production - username: <%= app_name %> - password: + 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 175f3eb3db..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 @@ -4,17 +4,21 @@ # Configure Using Gemfile # gem 'activerecord-jdbcsqlite3-adapter' # -development: +default: &default adapter: sqlite3 + +development: + <<: *default database: db/development.sqlite3 # Warning: The database defined as "test" will be erased and # re-generated from your development database when you run "rake". # Do not set this db to the same as development or production. test: - adapter: sqlite3 + <<: *default database: db/test.sqlite3 +# Do not keep production credentials in the repository, +# instead read the configuration from the environment. production: - adapter: sqlite3 - 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 c3349912aa..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 @@ -8,10 +8,10 @@ # # And be sure to use new-style password hashing: # http://dev.mysql.com/doc/refman/5.0/en/old-client.html -development: +# +default: &default adapter: mysql2 encoding: utf8 - database: <%= app_name %>_development pool: 5 username: root password: @@ -21,31 +21,22 @@ development: host: localhost <% end -%> +development: + <<: *default + database: <%= app_name %>_development + # Warning: The database defined as "test" will be erased and # re-generated from your development database when you run "rake". # Do not set this db to the same as development or production. test: - adapter: mysql2 - encoding: utf8 + <<: *default database: <%= app_name %>_test - pool: 5 - username: root - password: -<% if mysql_socket -%> - socket: <%= mysql_socket %> -<% else -%> - host: localhost -<% end -%> +# Avoid production credentials in the repository, +# instead read the configuration from the environment. +# +# Example: +# mysql2://myuser:mypass@localhost/somedatabase +# production: - adapter: mysql2 - encoding: utf8 - database: <%= app_name %>_production - pool: 5 - username: root - password: -<% if mysql_socket -%> - socket: <%= mysql_socket %> -<% else -%> - host: localhost -<% end -%> + 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 b661a60389..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 @@ -16,24 +16,23 @@ # prefetch_rows: 100 # cursor_sharing: similar # - -development: +default: &default adapter: oracle - database: <%= app_name %>_development username: <%= app_name %> password: +development: + <<: *default + database: <%= app_name %>_development + # Warning: The database defined as "test" will be erased and # re-generated from your development database when you run "rake". # Do not set this db to the same as development or production. test: - adapter: oracle + <<: *default database: <%= app_name %>_test - username: <%= app_name %> - password: +# Do not keep production credentials in the repository, +# instead read the configuration from the environment. production: - adapter: oracle - database: <%= app_name %>_production - username: <%= app_name %> - password: + 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 eb569b7dab..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 @@ -14,13 +14,25 @@ # Configure Using Gemfile # gem 'pg' # -development: +default: &default adapter: postgresql encoding: unicode - database: <%= app_name %>_development + # 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 @@ -44,17 +56,14 @@ development: # re-generated from your development database when you run "rake". # Do not set this db to the same as development or production. test: - adapter: postgresql - encoding: unicode + <<: *default database: <%= app_name %>_test - pool: 5 - username: <%= app_name %> - password: +# Do not keep production credentials in the repository, +# instead read the configuration from the environment. +# +# Example: +# postgres://myuser:mypass@localhost/somedatabase +# production: - adapter: postgresql - encoding: unicode - database: <%= app_name %>_production - pool: 5 - username: <%= app_name %> - password: + 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 51a4dd459d..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 @@ -3,23 +3,28 @@ # # Ensure the SQLite 3 gem is defined in your Gemfile # gem 'sqlite3' -development: +# +default: &default adapter: sqlite3 - database: db/development.sqlite3 pool: 5 timeout: 5000 +development: + <<: *default + database: db/development.sqlite3 + # Warning: The database defined as "test" will be erased and # re-generated from your development database when you run "rake". # Do not set this db to the same as development or production. test: - adapter: sqlite3 + <<: *default database: db/test.sqlite3 - pool: 5 - timeout: 5000 +# 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: - adapter: sqlite3 - database: db/production.sqlite3 - pool: 5 - timeout: 5000 + 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 7ef89d6608..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 @@ -21,37 +21,28 @@ # If you can connect with "tsql -S servername", your basic FreeTDS installation is working. # 'man tsql' for more info # Set timeout to a larger number if valid queries against a live db fail - -development: +# +default: &default adapter: sqlserver encoding: utf8 reconnect: false - database: <%= app_name %>_development username: <%= app_name %> password: timeout: 25 dataserver: from_freetds.conf +development: + <<: *default + database: <%= app_name %>_development # Warning: The database defined as "test" will be erased and # re-generated from your development database when you run "rake". # Do not set this db to the same as development or production. test: - adapter: sqlserver - encoding: utf8 - reconnect: false + <<: *default database: <%= app_name %>_test - username: <%= app_name %> - password: - timeout: 25 - dataserver: from_freetds.conf +# Do not keep production credentials in the repository, +# instead read the configuration from the environment. production: - adapter: sqlserver - encoding: utf8 - reconnect: false - database: <%= app_name %>_production - username: <%= app_name %> - password: - timeout: 25 - dataserver: from_freetds.conf + 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 91253d1508..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 @@ -20,14 +20,19 @@ Rails.application.configure do config.active_support.deprecation = :log <%- unless options.skip_active_record? -%> - # Raise an error on page load if there are pending migrations + # Raise an error on page load if there are pending migrations. config.active_record.migration_error = :page_load - <%- end -%> + <%- end -%> <%- unless options.skip_sprockets? -%> # Debug mode disables concatenation and preprocessing of assets. # 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/routes.rb b/railties/lib/rails/generators/rails/app/templates/config/routes.rb index 3dfb724164..3f66539d54 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/routes.rb +++ b/railties/lib/rails/generators/rails/app/templates/config/routes.rb @@ -39,7 +39,7 @@ Rails.application.routes.draw do # get 'recent', on: :collection # end # end - + # Example resource route with concerns: # concern :toggleable do # post 'toggle' 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/public/404.html b/railties/lib/rails/generators/rails/app/templates/public/404.html index a0daa0c156..b612547fc2 100644 --- a/railties/lib/rails/generators/rails/app/templates/public/404.html +++ b/railties/lib/rails/generators/rails/app/templates/public/404.html @@ -2,17 +2,23 @@ <html> <head> <title>The page you were looking for doesn't exist (404)</title> + <meta name="viewport" content="width=device-width,initial-scale=1"> <style> body { background-color: #EFEFEF; color: #2E2F30; text-align: center; font-family: arial, sans-serif; + margin: 0; } div.dialog { - width: 25em; - margin: 4em auto 0 auto; + width: 95%; + max-width: 33em; + margin: 4em auto 0; + } + + div.dialog > div { border: 1px solid #CCC; border-right-color: #999; border-left-color: #999; @@ -21,7 +27,8 @@ border-top-left-radius: 9px; border-top-right-radius: 9px; background-color: white; - padding: 7px 4em 0 4em; + padding: 7px 12% 0; + box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17); } h1 { @@ -30,19 +37,19 @@ line-height: 1.5em; } - body > p { - width: 33em; - margin: 0 auto 1em; - padding: 1em 0; + div.dialog > p { + margin: 0 0 1em; + padding: 1em; background-color: #F7F7F7; border: 1px solid #CCC; border-right-color: #999; + border-left-color: #999; border-bottom-color: #999; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-color: #DADADA; color: #666; - box-shadow:0 3px 8px rgba(50, 50, 50, 0.17); + box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17); } </style> </head> @@ -50,9 +57,11 @@ <body> <!-- This file lives in public/404.html --> <div class="dialog"> - <h1>The page you were looking for doesn't exist.</h1> - <p>You may have mistyped the address or the page may have moved.</p> + <div> + <h1>The page you were looking for doesn't exist.</h1> + <p>You may have mistyped the address or the page may have moved.</p> + </div> + <p>If you are the application owner check the logs for more information.</p> </div> - <p>If you are the application owner check the logs for more information.</p> </body> </html> diff --git a/railties/lib/rails/generators/rails/app/templates/public/422.html b/railties/lib/rails/generators/rails/app/templates/public/422.html index fbb4b84d72..a21f82b3bd 100644 --- a/railties/lib/rails/generators/rails/app/templates/public/422.html +++ b/railties/lib/rails/generators/rails/app/templates/public/422.html @@ -2,17 +2,23 @@ <html> <head> <title>The change you wanted was rejected (422)</title> + <meta name="viewport" content="width=device-width,initial-scale=1"> <style> body { background-color: #EFEFEF; color: #2E2F30; text-align: center; font-family: arial, sans-serif; + margin: 0; } div.dialog { - width: 25em; - margin: 4em auto 0 auto; + width: 95%; + max-width: 33em; + margin: 4em auto 0; + } + + div.dialog > div { border: 1px solid #CCC; border-right-color: #999; border-left-color: #999; @@ -21,7 +27,8 @@ border-top-left-radius: 9px; border-top-right-radius: 9px; background-color: white; - padding: 7px 4em 0 4em; + padding: 7px 12% 0; + box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17); } h1 { @@ -30,19 +37,19 @@ line-height: 1.5em; } - body > p { - width: 33em; - margin: 0 auto 1em; - padding: 1em 0; + div.dialog > p { + margin: 0 0 1em; + padding: 1em; background-color: #F7F7F7; border: 1px solid #CCC; border-right-color: #999; + border-left-color: #999; border-bottom-color: #999; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-color: #DADADA; color: #666; - box-shadow:0 3px 8px rgba(50, 50, 50, 0.17); + box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17); } </style> </head> @@ -50,9 +57,11 @@ <body> <!-- This file lives in public/422.html --> <div class="dialog"> - <h1>The change you wanted was rejected.</h1> - <p>Maybe you tried to change something you didn't have access to.</p> + <div> + <h1>The change you wanted was rejected.</h1> + <p>Maybe you tried to change something you didn't have access to.</p> + </div> + <p>If you are the application owner check the logs for more information.</p> </div> - <p>If you are the application owner check the logs for more information.</p> </body> </html> diff --git a/railties/lib/rails/generators/rails/app/templates/public/500.html b/railties/lib/rails/generators/rails/app/templates/public/500.html index e9052d35bf..061abc587d 100644 --- a/railties/lib/rails/generators/rails/app/templates/public/500.html +++ b/railties/lib/rails/generators/rails/app/templates/public/500.html @@ -2,17 +2,23 @@ <html> <head> <title>We're sorry, but something went wrong (500)</title> + <meta name="viewport" content="width=device-width,initial-scale=1"> <style> body { background-color: #EFEFEF; color: #2E2F30; text-align: center; font-family: arial, sans-serif; + margin: 0; } div.dialog { - width: 25em; - margin: 4em auto 0 auto; + width: 95%; + max-width: 33em; + margin: 4em auto 0; + } + + div.dialog > div { border: 1px solid #CCC; border-right-color: #999; border-left-color: #999; @@ -21,7 +27,8 @@ border-top-left-radius: 9px; border-top-right-radius: 9px; background-color: white; - padding: 7px 4em 0 4em; + padding: 7px 12% 0; + box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17); } h1 { @@ -30,19 +37,19 @@ line-height: 1.5em; } - body > p { - width: 33em; - margin: 0 auto 1em; - padding: 1em 0; + div.dialog > p { + margin: 0 0 1em; + padding: 1em; background-color: #F7F7F7; border: 1px solid #CCC; border-right-color: #999; + border-left-color: #999; border-bottom-color: #999; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-color: #DADADA; color: #666; - box-shadow:0 3px 8px rgba(50, 50, 50, 0.17); + box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17); } </style> </head> @@ -50,8 +57,10 @@ <body> <!-- This file lives in public/500.html --> <div class="dialog"> - <h1>We're sorry, but something went wrong.</h1> + <div> + <h1>We're sorry, but something went wrong.</h1> + </div> + <p>If you are the application owner check the logs for more information.</p> </div> - <p>If you are the application owner check the logs for more information.</p> </body> </html> diff --git a/railties/lib/rails/generators/rails/app/templates/public/robots.txt b/railties/lib/rails/generators/rails/app/templates/public/robots.txt index 1a3a5e4dd2..3c9c7c01f3 100644 --- a/railties/lib/rails/generators/rails/app/templates/public/robots.txt +++ b/railties/lib/rails/generators/rails/app/templates/public/robots.txt @@ -1,4 +1,4 @@ -# See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file +# See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file # # To ban all spiders from the entire site uncomment the next two lines: # User-agent: * 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/controller/USAGE b/railties/lib/rails/generators/rails/controller/USAGE index 64239ad599..de33900e0a 100644 --- a/railties/lib/rails/generators/rails/controller/USAGE +++ b/railties/lib/rails/generators/rails/controller/USAGE @@ -16,3 +16,4 @@ Example: Test: test/controllers/credit_cards_controller_test.rb Views: app/views/credit_cards/debit.html.erb [...] Helper: app/helpers/credit_cards_helper.rb + Test: test/helpers/credit_cards_helper_test.rb diff --git a/railties/lib/rails/generators/rails/controller/controller_generator.rb b/railties/lib/rails/generators/rails/controller/controller_generator.rb index bae54623c6..ef84447df9 100644 --- a/railties/lib/rails/generators/rails/controller/controller_generator.rb +++ b/railties/lib/rails/generators/rails/controller/controller_generator.rb @@ -10,11 +10,45 @@ module Rails def add_routes actions.reverse.each do |action| - route %{get "#{file_name}/#{action}"} + route generate_routing_code(action) end end hook_for :template_engine, :test_framework, :helper, :assets + + private + + # This method creates nested route entry for namespaced resources. + # For eg. rails g controller foo/bar/baz index + # Will generate - + # namespace :foo do + # namespace :bar do + # get "baz/index" + # end + # end + def generate_routing_code(action) + depth = class_path.length + # Create 'namespace' ladder + # namespace :foo do + # namespace :bar do + namespace_ladder = class_path.each_with_index.map do |ns, i| + indent("namespace :#{ns} do\n", i * 2) + end.join + + # Create route + # get "baz/index" + route = indent(%{get "#{file_name}/#{action}"\n}, depth * 2) + + # Create `end` ladder + # end + # end + end_ladder = (1..depth).reverse_each.map do |i| + indent("end\n", i * 2) + end.join + + # Combine the 3 parts to generate complete route entry + namespace_ladder + route + end_ladder + end end end end diff --git a/railties/lib/rails/generators/rails/generator/USAGE b/railties/lib/rails/generators/rails/generator/USAGE index d28eb3d7d8..799383050c 100644 --- a/railties/lib/rails/generators/rails/generator/USAGE +++ b/railties/lib/rails/generators/rails/generator/USAGE @@ -10,3 +10,4 @@ Example: lib/generators/awesome/awesome_generator.rb lib/generators/awesome/USAGE lib/generators/awesome/templates/ + test/lib/generators/awesome_generator_test.rb diff --git a/railties/lib/rails/generators/rails/generator/generator_generator.rb b/railties/lib/rails/generators/rails/generator/generator_generator.rb index 9a7a516b5b..15d88f06ac 100644 --- a/railties/lib/rails/generators/rails/generator/generator_generator.rb +++ b/railties/lib/rails/generators/rails/generator/generator_generator.rb @@ -10,6 +10,8 @@ module Rails directory '.', generator_dir end + hook_for :test_framework + protected def generator_dir diff --git a/railties/lib/rails/generators/rails/model/USAGE b/railties/lib/rails/generators/rails/model/USAGE index 145d9ee6e0..833b7beb7f 100644 --- a/railties/lib/rails/generators/rails/model/USAGE +++ b/railties/lib/rails/generators/rails/model/USAGE @@ -60,7 +60,7 @@ Available field types: For decimal, two integers separated by a comma in curly braces will be used for precision and scale: - `rails generate model product price:decimal{10,2}` + `rails generate model product 'price:decimal{10,2}'` You can add a `:uniq` or `:index` suffix for unique or standard indexes respectively: diff --git a/railties/lib/rails/generators/rails/plugin_new/USAGE b/railties/lib/rails/generators/rails/plugin/USAGE index 9a7bf9f396..9a7bf9f396 100644 --- a/railties/lib/rails/generators/rails/plugin_new/USAGE +++ b/railties/lib/rails/generators/rails/plugin/USAGE diff --git a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb b/railties/lib/rails/generators/rails/plugin/plugin_generator.rb index 850c9d5c0d..dbe1e37d8e 100644 --- a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb +++ b/railties/lib/rails/generators/rails/plugin/plugin_generator.rb @@ -154,7 +154,7 @@ task default: :test end module Generators - class PluginNewGenerator < AppBase # :nodoc: + class PluginGenerator < AppBase # :nodoc: add_shared_options_for "plugin" alias_method :plugin_path, :app_path @@ -176,12 +176,16 @@ task default: :test "skip adding entry to Gemfile" def initialize(*args) - raise Error, "Options should be given after the plugin name. For details run: rails plugin new --help" if args[0].blank? - @dummy_path = nil super + + unless plugin_path + raise Error, "Plugin name should be provided in arguments. For details run: rails plugin new --help" + end end + public_task :set_default_accessors! + public_task :apply_rails_template public_task :create_root def create_root_files @@ -238,7 +242,6 @@ task default: :test build(:leftovers) end - public_task :apply_rails_template, :run_bundle def name @name ||= begin @@ -252,6 +255,9 @@ task default: :test end end + public_task :run_bundle + public_task :replay_template + protected def app_templates_dir @@ -317,7 +323,7 @@ task default: :test @application_definition ||= begin dummy_application_path = File.expand_path("#{dummy_path}/config/application.rb", destination_root) - unless options[:pretend] || !File.exists?(dummy_application_path) + unless options[:pretend] || !File.exist?(dummy_application_path) contents = File.read(dummy_application_path) contents[(contents.index(/module ([\w]+)\n(.*)class Application/m))..-1] end diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/%name%.gemspec b/railties/lib/rails/generators/rails/plugin/templates/%name%.gemspec index 5fdf0e1554..5fdf0e1554 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/%name%.gemspec +++ b/railties/lib/rails/generators/rails/plugin/templates/%name%.gemspec diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/Gemfile b/railties/lib/rails/generators/rails/plugin/templates/Gemfile index 3f2b78f2fd..88ec4e6354 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/Gemfile +++ b/railties/lib/rails/generators/rails/plugin/templates/Gemfile @@ -23,8 +23,23 @@ end <% if options.dev? || options.edge? -%> # Your gem is dependent on dev or edge Rails. Once you can lock this # dependency down to a specific version, move it to your gemspec. -<%= rails_gemfile_entry -%> +<% max_width = gemfile_entries.map { |g| g.name.length }.max -%> +<% gemfile_entries.each do |gem| -%> +<% if gem.comment -%> +# <%= gem.comment %> <% end -%> +<%= gem.commented_out ? '# ' : '' %>gem '<%= gem.name %>'<% if gem.version -%> +, '<%= gem.version %>' +<% elsif gem.options.any? -%> +,<%= gem.padding(max_width) %><%= gem.options.map { |k,v| + "#{k}: #{v.inspect}" }.join(', ') %> +<% else %> +<% end -%> +<% end -%> + +<% end -%> +<% unless defined?(JRUBY_VERSION) -%> # To use debugger # gem 'debugger' +<% end -%> diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/MIT-LICENSE b/railties/lib/rails/generators/rails/plugin/templates/MIT-LICENSE index d7a9109894..d7a9109894 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/MIT-LICENSE +++ b/railties/lib/rails/generators/rails/plugin/templates/MIT-LICENSE diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/README.rdoc b/railties/lib/rails/generators/rails/plugin/templates/README.rdoc index 301d647731..301d647731 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/README.rdoc +++ b/railties/lib/rails/generators/rails/plugin/templates/README.rdoc diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/Rakefile b/railties/lib/rails/generators/rails/plugin/templates/Rakefile index 0ba899176c..0ba899176c 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/Rakefile +++ b/railties/lib/rails/generators/rails/plugin/templates/Rakefile diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/app/controllers/%name%/application_controller.rb.tt b/railties/lib/rails/generators/rails/plugin/templates/app/controllers/%name%/application_controller.rb.tt index 448ad7f989..448ad7f989 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/app/controllers/%name%/application_controller.rb.tt +++ b/railties/lib/rails/generators/rails/plugin/templates/app/controllers/%name%/application_controller.rb.tt diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/app/helpers/%name%/application_helper.rb.tt b/railties/lib/rails/generators/rails/plugin/templates/app/helpers/%name%/application_helper.rb.tt index 40ae9f52c2..40ae9f52c2 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/app/helpers/%name%/application_helper.rb.tt +++ b/railties/lib/rails/generators/rails/plugin/templates/app/helpers/%name%/application_helper.rb.tt diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/app/mailers/.empty_directory b/railties/lib/rails/generators/rails/plugin/templates/app/mailers/.empty_directory index e69de29bb2..e69de29bb2 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/app/mailers/.empty_directory +++ b/railties/lib/rails/generators/rails/plugin/templates/app/mailers/.empty_directory diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/app/models/.empty_directory b/railties/lib/rails/generators/rails/plugin/templates/app/models/.empty_directory index e69de29bb2..e69de29bb2 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/app/models/.empty_directory +++ b/railties/lib/rails/generators/rails/plugin/templates/app/models/.empty_directory diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/app/views/layouts/%name%/application.html.erb.tt b/railties/lib/rails/generators/rails/plugin/templates/app/views/layouts/%name%/application.html.erb.tt index 1d380420b4..1d380420b4 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/app/views/layouts/%name%/application.html.erb.tt +++ b/railties/lib/rails/generators/rails/plugin/templates/app/views/layouts/%name%/application.html.erb.tt diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/bin/rails.tt b/railties/lib/rails/generators/rails/plugin/templates/bin/rails.tt index c8de9f3e0f..c8de9f3e0f 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/bin/rails.tt +++ b/railties/lib/rails/generators/rails/plugin/templates/bin/rails.tt diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/config/routes.rb b/railties/lib/rails/generators/rails/plugin/templates/config/routes.rb index 8e158d5831..8e158d5831 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/config/routes.rb +++ b/railties/lib/rails/generators/rails/plugin/templates/config/routes.rb diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/gitignore b/railties/lib/rails/generators/rails/plugin/templates/gitignore index 086d87818a..086d87818a 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/gitignore +++ b/railties/lib/rails/generators/rails/plugin/templates/gitignore diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/lib/%name%.rb b/railties/lib/rails/generators/rails/plugin/templates/lib/%name%.rb index 40c074cced..40c074cced 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/lib/%name%.rb +++ b/railties/lib/rails/generators/rails/plugin/templates/lib/%name%.rb diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/lib/%name%/engine.rb b/railties/lib/rails/generators/rails/plugin/templates/lib/%name%/engine.rb index 967668fe66..967668fe66 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/lib/%name%/engine.rb +++ b/railties/lib/rails/generators/rails/plugin/templates/lib/%name%/engine.rb diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/lib/%name%/version.rb b/railties/lib/rails/generators/rails/plugin/templates/lib/%name%/version.rb index ef07ef2e19..ef07ef2e19 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/lib/%name%/version.rb +++ b/railties/lib/rails/generators/rails/plugin/templates/lib/%name%/version.rb diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/lib/tasks/%name%_tasks.rake b/railties/lib/rails/generators/rails/plugin/templates/lib/tasks/%name%_tasks.rake index 7121f5ae23..7121f5ae23 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/lib/tasks/%name%_tasks.rake +++ b/railties/lib/rails/generators/rails/plugin/templates/lib/tasks/%name%_tasks.rake diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/rails/application.rb b/railties/lib/rails/generators/rails/plugin/templates/rails/application.rb index 310c975262..5508829f6b 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/rails/application.rb +++ b/railties/lib/rails/generators/rails/plugin/templates/rails/application.rb @@ -7,6 +7,7 @@ require 'rails/all' <%= comment_if :skip_active_record %>require "active_record/railtie" require "action_controller/railtie" require "action_mailer/railtie" +<%= comment_if :skip_action_view %>require "action_view/railtie" <%= comment_if :skip_sprockets %>require "sprockets/railtie" <%= comment_if :skip_test_unit %>require "rails/test_unit/railtie" <% end -%> diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/rails/boot.rb b/railties/lib/rails/generators/rails/plugin/templates/rails/boot.rb index ef360470a3..6266cfc509 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/rails/boot.rb +++ b/railties/lib/rails/generators/rails/plugin/templates/rails/boot.rb @@ -1,5 +1,5 @@ # Set up gems listed in the Gemfile. ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../../../Gemfile', __FILE__) -require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE']) +require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE']) $LOAD_PATH.unshift File.expand_path('../../../../lib', __FILE__) diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/rails/javascripts.js b/railties/lib/rails/generators/rails/plugin/templates/rails/javascripts.js index f84de00fd3..5bc2e1c8b5 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/rails/javascripts.js +++ b/railties/lib/rails/generators/rails/plugin/templates/rails/javascripts.js @@ -7,6 +7,7 @@ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the // compiled file. // -// stub path allows dependency to be excluded from the asset bundle. +// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details +// about supported directives. // //= require_tree . diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/rails/routes.rb b/railties/lib/rails/generators/rails/plugin/templates/rails/routes.rb index 730ee31c3d..730ee31c3d 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/rails/routes.rb +++ b/railties/lib/rails/generators/rails/plugin/templates/rails/routes.rb diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/rails/stylesheets.css b/railties/lib/rails/generators/rails/plugin/templates/rails/stylesheets.css index 3192ec897b..a443db3401 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/rails/stylesheets.css +++ b/railties/lib/rails/generators/rails/plugin/templates/rails/stylesheets.css @@ -5,9 +5,11 @@ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path. * - * You're free to add application-wide styles to this file and they'll appear at the top of the - * compiled file, but it's generally better to create a new file per style scope. + * You're free to add application-wide styles to this file and they'll appear at the bottom of the + * compiled file so the styles you add here take precedence over styles defined in any styles + * defined in the other CSS/SCSS files in this directory. It is generally better to create a new + * file per style scope. * - *= require_self *= require_tree . + *= require_self */ diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/test/%name%_test.rb b/railties/lib/rails/generators/rails/plugin/templates/test/%name%_test.rb index 0a8bbd4aaf..0a8bbd4aaf 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/test/%name%_test.rb +++ b/railties/lib/rails/generators/rails/plugin/templates/test/%name%_test.rb diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/test/integration/navigation_test.rb b/railties/lib/rails/generators/rails/plugin/templates/test/integration/navigation_test.rb index 824caecb24..824caecb24 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/test/integration/navigation_test.rb +++ b/railties/lib/rails/generators/rails/plugin/templates/test/integration/navigation_test.rb diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/test/test_helper.rb b/railties/lib/rails/generators/rails/plugin/templates/test/test_helper.rb index 1e26a313cd..1e26a313cd 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/test/test_helper.rb +++ b/railties/lib/rails/generators/rails/plugin/templates/test/test_helper.rb 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/rails/scaffold_controller/scaffold_controller_generator.rb b/railties/lib/rails/generators/rails/scaffold_controller/scaffold_controller_generator.rb index 4f36b612ae..6bf0a33a5f 100644 --- a/railties/lib/rails/generators/rails/scaffold_controller/scaffold_controller_generator.rb +++ b/railties/lib/rails/generators/rails/scaffold_controller/scaffold_controller_generator.rb @@ -13,7 +13,7 @@ module Rails argument :attributes, type: :array, default: [], banner: "field:type field:type" def create_controller_files - template "controller.rb", File.join('app/controllers', class_path, "#{controller_file_name}_controller.rb") + template "controller.rb", File.join('app/controllers', controller_class_path, "#{controller_file_name}_controller.rb") end hook_for :template_engine, :test_framework, as: :scaffold diff --git a/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb b/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb index 73e89086a5..0e69aa101f 100644 --- a/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb +++ b/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb @@ -59,9 +59,9 @@ class <%= controller_class_name %>Controller < ApplicationController # Only allow a trusted parameter "white list" through. def <%= "#{singular_table_name}_params" %> <%- if attributes_names.empty? -%> - params[<%= ":#{singular_table_name}" %>] + params[:<%= singular_table_name %>] <%- else -%> - params.require(<%= ":#{singular_table_name}" %>).permit(<%= attributes_names.map { |name| ":#{name}" }.join(', ') %>) + params.require(:<%= singular_table_name %>).permit(<%= attributes_names.map { |name| ":#{name}" }.join(', ') %>) <%- end -%> end end diff --git a/railties/lib/rails/generators/resource_helpers.rb b/railties/lib/rails/generators/resource_helpers.rb index 7fd5c00768..a01eb57651 100644 --- a/railties/lib/rails/generators/resource_helpers.rb +++ b/railties/lib/rails/generators/resource_helpers.rb @@ -9,11 +9,19 @@ module Rails def self.included(base) #:nodoc: base.class_option :force_plural, type: :boolean, desc: "Forces the use of a plural ModelName" + base.class_option :model_name, type: :string, desc: "ModelName to be used" end # Set controller variables on initialization. def initialize(*args) #:nodoc: super + if options[:model_name] + controller_name = name + self.name = options[:model_name] + assign_names!(self.name) + else + controller_name = name + end if name == name.pluralize && name.singularize != name.pluralize && !options[:force_plural] unless ResourceHelpers.skip_warn @@ -24,19 +32,26 @@ module Rails assign_names!(name) end - @controller_name = name.pluralize + assign_controller_names!(controller_name.pluralize) end protected - attr_reader :controller_name + attr_reader :controller_name, :controller_file_name def controller_class_path - class_path + if options[:model_name] + @controller_class_path + else + class_path + end end - def controller_file_name - @controller_file_name ||= file_name.pluralize + def assign_controller_names!(name) + @controller_name = name + @controller_class_path = name.include?('/') ? name.split('/') : name.split('::') + @controller_class_path.map! { |m| m.underscore } + @controller_file_name = @controller_class_path.pop end def controller_file_path diff --git a/railties/lib/rails/generators/test_unit/generator/generator_generator.rb b/railties/lib/rails/generators/test_unit/generator/generator_generator.rb new file mode 100644 index 0000000000..d7307398ce --- /dev/null +++ b/railties/lib/rails/generators/test_unit/generator/generator_generator.rb @@ -0,0 +1,26 @@ +require 'rails/generators/test_unit' + +module TestUnit # :nodoc: + module Generators # :nodoc: + class GeneratorGenerator < Base # :nodoc: + check_class_collision suffix: "GeneratorTest" + + class_option :namespace, type: :boolean, default: true, + desc: "Namespace generator under lib/generators/name" + + def create_generator_files + template 'generator_test.rb', File.join('test/lib/generators', class_path, "#{file_name}_generator_test.rb") + end + + protected + + def generator_path + if options[:namespace] + File.join("generators", regular_class_path, file_name, "#{file_name}_generator") + else + File.join("generators", regular_class_path, "#{file_name}_generator") + end + end + end + end +end diff --git a/railties/lib/rails/generators/test_unit/generator/templates/generator_test.rb b/railties/lib/rails/generators/test_unit/generator/templates/generator_test.rb new file mode 100644 index 0000000000..a7f1fc4fba --- /dev/null +++ b/railties/lib/rails/generators/test_unit/generator/templates/generator_test.rb @@ -0,0 +1,16 @@ +require 'test_helper' +require '<%= generator_path %>' + +<% module_namespacing do -%> +class <%= class_name %>GeneratorTest < Rails::Generators::TestCase + tests <%= class_name %>Generator + destination Rails.root.join('tmp/generators') + setup :prepare_destination + + # test "generator runs without errors" do + # assert_nothing_raised do + # run_generator ["arguments"] + # end + # end +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/test_unit/model/templates/fixtures.yml b/railties/lib/rails/generators/test_unit/model/templates/fixtures.yml index 90a92e6982..f19e9d1d87 100644 --- a/railties/lib/rails/generators/test_unit/model/templates/fixtures.yml +++ b/railties/lib/rails/generators/test_unit/model/templates/fixtures.yml @@ -1,4 +1,4 @@ -# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/Fixtures.html +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html <% unless attributes.empty? -%> <% %w(one two).each do |name| %> <%= name %>: diff --git a/railties/lib/rails/generators/testing/assertions.rb b/railties/lib/rails/generators/testing/assertions.rb index 6267b2f2ee..2e877f8762 100644 --- a/railties/lib/rails/generators/testing/assertions.rb +++ b/railties/lib/rails/generators/testing/assertions.rb @@ -21,8 +21,8 @@ module Rails # end # end def assert_file(relative, *contents) - absolute = File.expand_path(relative, destination_root) - assert File.exists?(absolute), "Expected file #{relative.inspect} to exist, but does not" + absolute = File.expand_path(relative, destination_root).shellescape + assert File.exist?(absolute), "Expected file #{relative.inspect} to exist, but does not" read = File.read(absolute) if block_given? || !contents.empty? yield read if block_given? @@ -44,7 +44,7 @@ module Rails # assert_no_file "config/random.rb" def assert_no_file(relative) absolute = File.expand_path(relative, destination_root) - assert !File.exists?(absolute), "Expected file #{relative.inspect} to not exist, but does" + assert !File.exist?(absolute), "Expected file #{relative.inspect} to not exist, but does" end alias :assert_no_directory :assert_no_file 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.rb b/railties/lib/rails/info.rb index f06ce659c5..edadeaca0e 100644 --- a/railties/lib/rails/info.rb +++ b/railties/lib/rails/info.rb @@ -23,7 +23,7 @@ module Rails end def frameworks - %w( active_record action_pack action_mailer active_support ) + %w( active_record action_pack action_view action_mailer active_support ) end def framework_version(framework) @@ -61,8 +61,10 @@ module Rails end end - # The Ruby version and platform, e.g. "1.8.2 (powerpc-darwin8.2.0)". - property 'Ruby version', "#{RUBY_VERSION} (#{RUBY_PLATFORM})" + # The Ruby version and platform, e.g. "2.0.0-p247 (x86_64-darwin12.4.0)". + property 'Ruby version' do + "#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL} (#{RUBY_PLATFORM})" + end # The RubyGems version, if it's installed. property 'RubyGems version' do diff --git a/railties/lib/rails/info_controller.rb b/railties/lib/rails/info_controller.rb index fa5668a5b5..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! @@ -13,21 +13,11 @@ class Rails::InfoController < ActionController::Base # :nodoc: def properties @info = Rails::Info.to_html + @page_title = 'Properties' end def routes @routes_inspector = ActionDispatch::Routing::RoutesInspector.new(_routes.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? + @page_title = 'Routes' 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 de6795eda2..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"] @@ -81,34 +81,28 @@ module Rails end def autoload_once - filter_by(:autoload_once?) + filter_by { |p| p.autoload_once? } end def eager_load - filter_by(:eager_load?) + filter_by { |p| p.eager_load? } end def autoload_paths - filter_by(:autoload?) + filter_by { |p| p.autoload? } end def load_paths - filter_by(:load_path?) + filter_by { |p| p.load_path? } end - protected + private - def filter_by(constraint) - all = [] - all_paths.each do |path| - if path.send(constraint) - paths = path.existent - paths -= path.children.map { |p| p.send(constraint) ? [] : p.existent }.flatten - all.concat(paths) - end - end - all.uniq! - all + def filter_by(&block) + all_paths.find_all(&block).flat_map { |path| + paths = path.existent + paths - path.children.map { |p| yield(p) ? [] : p.existent }.flatten + }.uniq end end @@ -130,8 +124,9 @@ module Rails end def children - keys = @root.keys.select { |k| k.include?(@current) } - keys.delete(@current) + keys = @root.keys.find_all { |k| + k.start_with?(@current) && k != @current + } @root.values_at(*keys.sort) end @@ -203,7 +198,7 @@ module Rails # Returns all expanded paths but only if they exist in the filesystem. def existent - expanded.select { |f| File.exists?(f) } + expanded.select { |f| File.exist?(f) } end def existent_directories diff --git a/railties/lib/rails/rack/log_tailer.rb b/railties/lib/rails/rack/log_tailer.rb index 18f22e8089..50d0eb96fc 100644 --- a/railties/lib/rails/rack/log_tailer.rb +++ b/railties/lib/rails/rack/log_tailer.rb @@ -7,7 +7,7 @@ module Rails path = Pathname.new(log || "#{::File.expand_path(Rails.root)}/log/#{Rails.env}.log").cleanpath @cursor = @file = nil - if ::File.exists?(path) + if ::File.exist?(path) @cursor = ::File.size(path) @file = ::File.open(path, 'r') end diff --git a/railties/lib/rails/rack/logger.rb b/railties/lib/rails/rack/logger.rb index 6ed6722c44..3b35798679 100644 --- a/railties/lib/rails/rack/logger.rb +++ b/railties/lib/rails/rack/logger.rb @@ -11,7 +11,6 @@ module Rails def initialize(app, taggers = nil) @app = app @taggers = taggers || [] - @instrumenter = ActiveSupport::Notifications.instrumenter end def call(env) @@ -33,12 +32,13 @@ module Rails logger.debug '' end - @instrumenter.start 'action_dispatch.request', request: request + instrumenter = ActiveSupport::Notifications.instrumenter + instrumenter.start 'request.action_dispatch', request: request logger.info started_request_message(request) resp = @app.call(env) resp[2] = ::Rack::BodyProxy.new(resp[2]) { finish(request) } resp - rescue + rescue Exception finish(request) raise ensure @@ -70,7 +70,8 @@ module Rails private def finish(request) - @instrumenter.finish 'action_dispatch.request', request: request + instrumenter = ActiveSupport::Notifications.instrumenter + instrumenter.finish 'request.action_dispatch', request: request end def development? 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/railtie/configuration.rb b/railties/lib/rails/railtie/configuration.rb index 0cbbf04da2..eb3b2d8ef4 100644 --- a/railties/lib/rails/railtie/configuration.rb +++ b/railties/lib/rails/railtie/configuration.rb @@ -80,7 +80,7 @@ module Rails to_prepare_blocks << blk if blk end - def respond_to?(name) + def respond_to?(name, include_private = false) super || @@options.key?(name.to_sym) end diff --git a/railties/lib/rails/source_annotation_extractor.rb b/railties/lib/rails/source_annotation_extractor.rb index 2cbb0a435c..3cf6a005ea 100644 --- a/railties/lib/rails/source_annotation_extractor.rb +++ b/railties/lib/rails/source_annotation_extractor.rb @@ -67,7 +67,7 @@ class SourceAnnotationExtractor # Returns a hash that maps filenames under +dir+ (recursively) to arrays # with their annotations. Only files with annotations are included. Files # with extension +.builder+, +.rb+, +.erb+, +.haml+, +.slim+, +.css+, - # +.scss+, +.js+, +.coffee+, and +.rake+ + # +.scss+, +.js+, +.coffee+, +.rake+, +.sass+ and +.less+ # are taken into account. def find_in(dir) results = {} @@ -82,7 +82,7 @@ class SourceAnnotationExtractor case item when /\.(builder|rb|coffee|rake)$/ /#\s*(#{tag}):?\s*(.*)$/ - when /\.(css|scss|js)$/ + when /\.(css|scss|sass|less|js)$/ /\/\/\s*(#{tag}):?\s*(.*)$/ when /\.erb$/ /<%\s*#\s*(#{tag}):?\s*(.*?)\s*%>/ diff --git a/railties/lib/rails/tasks.rb b/railties/lib/rails/tasks.rb index 142af2d792..af5f2707b1 100644 --- a/railties/lib/rails/tasks.rb +++ b/railties/lib/rails/tasks.rb @@ -1,5 +1,3 @@ -$VERBOSE = nil - # Load Rails Rakefile extensions %w( annotations diff --git a/railties/lib/rails/tasks/engine.rake b/railties/lib/rails/tasks/engine.rake index 70370be3f5..16ad1bfc84 100644 --- a/railties/lib/rails/tasks/engine.rake +++ b/railties/lib/rails/tasks/engine.rake @@ -26,7 +26,7 @@ namespace :db do desc "Display status of migrations" app_task "migrate:status" - desc 'Create the database from config/database.yml for the current Rails.env (use db:create:all to create all dbs in the config)' + desc 'Create the database from config/database.yml for the current Rails.env (use db:create:all to create all databases in the config)' app_task "create" app_task "create:all" diff --git a/railties/lib/rails/tasks/framework.rake b/railties/lib/rails/tasks/framework.rake index 2116330b45..e669315934 100644 --- a/railties/lib/rails/tasks/framework.rake +++ b/railties/lib/rails/tasks/framework.rake @@ -1,6 +1,6 @@ namespace :rails do - desc "Update configs and some other initially generated files (or use just update:configs, update:bin, or update:application_controller)" - task update: [ "update:configs", "update:bin", "update:application_controller" ] + desc "Update configs and some other initially generated files (or use just update:configs or update:bin)" + task update: [ "update:configs", "update:bin" ] desc "Applies the template supplied by LOCATION=(/path/to/template) or URL" task :template do @@ -46,8 +46,8 @@ namespace :rails do require 'rails/generators/rails/app/app_generator' gen = Rails::Generators::AppGenerator.new ["rails"], { with_dispatchers: true }, destination_root: Rails.root - File.exists?(Rails.root.join("config", "application.rb")) ? - gen.send(:app_const) : gen.send(:valid_app_const?) + File.exist?(Rails.root.join("config", "application.rb")) ? + gen.send(:app_const) : gen.send(:valid_const?) gen end end @@ -62,15 +62,5 @@ namespace :rails do task :bin do invoke_from_app_generator :create_bin_files end - - # desc "Rename application.rb to application_controller.rb" - task :application_controller do - old_style = Rails.root + '/app/controllers/application.rb' - new_style = Rails.root + '/app/controllers/application_controller.rb' - if File.exists?(old_style) && !File.exists?(new_style) - FileUtils.mv(old_style, new_style) - puts "#{old_style} has been renamed to #{new_style}, update your SCM as necessary" - end - end end end diff --git a/railties/lib/rails/tasks/log.rake b/railties/lib/rails/tasks/log.rake index 6c3f02eb0c..877f175ef3 100644 --- a/railties/lib/rails/tasks/log.rake +++ b/railties/lib/rails/tasks/log.rake @@ -10,7 +10,7 @@ namespace :log do if ENV['LOGS'] ENV['LOGS'].split(',') .map { |file| "log/#{file.strip}.log" } - .select { |file| File.exists?(file) } + .select { |file| File.exist?(file) } else FileList["log/*.log"] end diff --git a/railties/lib/rails/templates/layouts/application.html.erb b/railties/lib/rails/templates/layouts/application.html.erb index 7352d48e7b..5aecaa712a 100644 --- a/railties/lib/rails/templates/layouts/application.html.erb +++ b/railties/lib/rails/templates/layouts/application.html.erb @@ -2,7 +2,7 @@ <html lang="en"> <head> <meta charset="utf-8" /> - <title>Routes</title> + <title><%= @page_title %></title> <style> body { background-color: #fff; color: #333; } @@ -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/templates/rails/welcome/index.html.erb b/railties/lib/rails/templates/rails/welcome/index.html.erb index 4c4c80ecda..eb620caa00 100644 --- a/railties/lib/rails/templates/rails/welcome/index.html.erb +++ b/railties/lib/rails/templates/rails/welcome/index.html.erb @@ -232,8 +232,8 @@ </li> <li> - <h2>Create your database</h2> - <p>Run <code>rake db:create</code> to create your database. If you're not using SQLite (the default), edit <span class="filename">config/database.yml</span> with your username and password.</p> + <h2>Configure your database</h2> + <p>If you're not using SQLite (the default), edit <span class="filename">config/database.yml</span> with your username and password.</p> </li> </ol> </div> diff --git a/railties/lib/rails/test_help.rb b/railties/lib/rails/test_help.rb index 739e4ad992..2e6356343d 100644 --- a/railties/lib/rails/test_help.rb +++ b/railties/lib/rails/test_help.rb @@ -6,12 +6,17 @@ require 'active_support/testing/autorun' require 'active_support/test_case' require 'action_controller/test_case' require 'action_dispatch/testing/integration' +require 'rails/generators/test_case' # Config Rails backtrace in tests. require 'rails/backtrace_cleaner' -MiniTest.backtrace_filter = Rails.backtrace_cleaner +if ENV["BACKTRACE"].nil? + 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/railtie.rb b/railties/lib/rails/test_unit/railtie.rb index ab1ebe1f8c..75180ff978 100644 --- a/railties/lib/rails/test_unit/railtie.rb +++ b/railties/lib/rails/test_unit/railtie.rb @@ -1,4 +1,4 @@ -if defined?(Rake) && Rake.application.top_level_tasks.grep(/^(default$|test(:|$))/).any? +if defined?(Rake.application) && Rake.application.top_level_tasks.grep(/^(default$|test(:|$))/).any? ENV['RAILS_ENV'] ||= 'test' end diff --git a/railties/lib/rails/test_unit/sub_test_task.rb b/railties/lib/rails/test_unit/sub_test_task.rb index a463380e2d..d9bffba4d7 100644 --- a/railties/lib/rails/test_unit/sub_test_task.rb +++ b/railties/lib/rails/test_unit/sub_test_task.rb @@ -2,13 +2,53 @@ require 'rake/testtask' module Rails class TestTask < Rake::TestTask # :nodoc: all + # A utility class which is used primarily in "rails/test_unit/testing.rake" + # to help define rake tasks corresponding to <tt>rake test</tt>. + # + # This class takes a TestInfo class and defines the appropriate rake task + # based on the information, then invokes it. + class TestCreator + def initialize(info) + @info = info + end + + def invoke_rake_task + if @info.files.any? + create_and_run_single_test + reset_application_tasks + else + Rake::Task[ENV['TEST'] ? 'test:single' : 'test:run'].invoke + end + end + + private + + def create_and_run_single_test + Rails::TestTask.new('test:single') { |t| + t.test_files = @info.files + } + ENV['TESTOPTS'] ||= @info.opts + Rake::Task['test:single'].invoke + end + + def reset_application_tasks + Rake.application.top_level_tasks.replace @info.tasks + end + end + + # This is a utility class used by the <tt>TestTask::TestCreator</tt> class. + # This class takes a set of test tasks and checks to see if they correspond + # to test files (or can be transformed into test files). Calling <tt>files</tt> + # provides the set of test files and is used when initializing tests after + # a call to <tt>rake test</tt>. class TestInfo def initialize(tasks) @tasks = tasks + @files = nil end def files - @tasks.map { |task| + @files ||= @tasks.map { |task| [task, translate(task)].find { |file| test_file?(file) } }.compact end @@ -53,8 +93,9 @@ module Rails end end - def self.test_info(tasks) - TestInfo.new tasks + def self.test_creator(tasks) + info = TestInfo.new(tasks) + TestCreator.new(info) end def initialize(name = :test) diff --git a/railties/lib/rails/test_unit/testing.rake b/railties/lib/rails/test_unit/testing.rake index 9263b9b81d..285e2ce846 100644 --- a/railties/lib/rails/test_unit/testing.rake +++ b/railties/lib/rails/test_unit/testing.rake @@ -1,65 +1,11 @@ -require 'rbconfig' require 'rake/testtask' require 'rails/test_unit/sub_test_task' -require 'active_support/deprecation' - -TEST_CHANGES_SINCE = Time.now - 600 - -# Look up tests for recently modified sources. -def recent_tests(source_pattern, test_path, touched_since = 10.minutes.ago) - FileList[source_pattern].map do |path| - if File.mtime(path) > touched_since - tests = [] - source_dir = File.dirname(path).split("/") - source_file = File.basename(path, '.rb') - - # Support subdirs in app/models and app/controllers - modified_test_path = source_dir.length > 2 ? "#{test_path}/" << source_dir[1..source_dir.length].join('/') : test_path - - # For modified files in app/ run the tests for it. ex. /test/controllers/account_controller.rb - test = "#{modified_test_path}/#{source_file}_test.rb" - tests.push test if File.exist?(test) - - # For modified files in app, run tests in subdirs too. ex. /test/controllers/account/*_test.rb - test = "#{modified_test_path}/#{File.basename(path, '.rb').sub("_controller","")}" - FileList["#{test}/*_test.rb"].each { |f| tests.push f } if File.exist?(test) - - return tests - - end - end.flatten.compact -end - - -# Recreated here from Active Support because :uncommitted needs it before Rails is available -module Kernel - remove_method :silence_stderr # Removing old method to prevent method redefined warning - def silence_stderr - old_stderr = STDERR.dup - STDERR.reopen(RbConfig::CONFIG['host_os'] =~ /mswin|mingw/ ? 'NUL:' : '/dev/null') - STDERR.sync = true - yield - ensure - STDERR.reopen(old_stderr) - end -end task default: :test -desc 'Runs test:units, test:functionals, test:integration together' +desc 'Runs test:units, test:functionals, test:generators, test:integration together' task :test do - info = Rails::TestTask.test_info Rake.application.top_level_tasks - if info.files.any? - Rails::TestTask.new('test:single') { |t| - t.test_files = info.files - } - ENV['TESTOPTS'] ||= info.opts - Rake.application.top_level_tasks.replace info.tasks - - Rake::Task['test:single'].invoke - else - Rake::Task[ENV['TEST'] ? 'test:single' : 'test:run'].invoke - end + Rails::TestTask.test_creator(Rake.application.top_level_tasks).invoke_rake_task end namespace :test do @@ -67,7 +13,7 @@ namespace :test do # Placeholder task for other Railtie and plugins to enhance. See Active Record for an example. end - task :run => ['test:units', 'test:functionals', 'test:integration'] + task :run => ['test:units', 'test:functionals', 'test:generators', 'test:integration'] # Inspired by: http://ngauthier.com/2012/02/quick-tests-with-bash.html desc "Run tests quickly by merging all types and not resetting db" @@ -80,45 +26,6 @@ namespace :test do task :db => %w[db:test:prepare test:all] end - # Display deprecation message - task :deprecated do - ActiveSupport::Deprecation.warn "`rake #{ARGV.first}` is deprecated with no replacement." - end - - Rake::TestTask.new(recent: ["test:deprecated", "test:prepare"]) do |t| - since = TEST_CHANGES_SINCE - touched = FileList['test/**/*_test.rb'].select { |path| File.mtime(path) > since } + - recent_tests('app/models/**/*.rb', 'test/models', since) + - recent_tests('app/models/**/*.rb', 'test/unit', since) + - recent_tests('app/controllers/**/*.rb', 'test/controllers', since) + - recent_tests('app/controllers/**/*.rb', 'test/functional', since) - - t.test_files = touched.uniq - end - Rake::Task['test:recent'].comment = "Deprecated; Test recent changes" - - Rake::TestTask.new(uncommitted: ["test:deprecated", "test:prepare"]) do |t| - def t.file_list - if File.directory?(".svn") - changed_since_checkin = silence_stderr { `svn status` }.split.map { |path| path.chomp[7 .. -1] } - elsif system "git rev-parse --git-dir 2>&1 >/dev/null" - changed_since_checkin = silence_stderr { `git ls-files --modified --others --exclude-standard` }.split.map { |path| path.chomp } - else - abort "Not a Subversion or Git checkout." - end - - models = changed_since_checkin.select { |path| path =~ /app[\\\/]models[\\\/].*\.rb$/ } - controllers = changed_since_checkin.select { |path| path =~ /app[\\\/]controllers[\\\/].*\.rb$/ } - - unit_tests = models.map { |model| "test/models/#{File.basename(model, '.rb')}_test.rb" } + - models.map { |model| "test/unit/#{File.basename(model, '.rb')}_test.rb" } + - functional_tests = controllers.map { |controller| "test/controllers/#{File.basename(controller, '.rb')}_test.rb" } + - controllers.map { |controller| "test/functional/#{File.basename(controller, '.rb')}_test.rb" } - (unit_tests + functional_tests).uniq.select { |file| File.exist?(file) } - end - end - Rake::Task['test:uncommitted'].comment = "Deprecated; Test changes since last checkin (only Subversion and Git)" - Rails::TestTask.new(single: "test:prepare") ["models", "helpers", "controllers", "mailers", "integration"].each do |name| @@ -127,6 +34,10 @@ namespace :test do end end + Rails::TestTask.new(generators: "test:prepare") do |t| + t.pattern = "test/lib/generators/**/*_test.rb" + end + Rails::TestTask.new(units: "test:prepare") do |t| t.pattern = 'test/{models,helpers,unit}/**/*_test.rb' end 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 |