diff options
Diffstat (limited to 'railties')
60 files changed, 619 insertions, 193 deletions
diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md index 573b1f8f69..faf6846e4b 100644 --- a/railties/CHANGELOG.md +++ b/railties/CHANGELOG.md @@ -1,3 +1,46 @@ +* `rails server` will now honour the `PORT` environment variable + + *David Cornu* + +* Plugins generated using `rails plugin new` are now generated with the + version number set to 0.1.0. + + *Daniel Morris* + +* `I18n.load_path` is now reloaded under development so there's no need to + restart the server to make new locale files available. Also, I18n will no + longer raise for deleted locale files. + + *Kir Shatrov* + +* Add `bin/update` script to update development environment automatically. + + *Mehmet Emin İNAÇ* + +* Fix STATS_DIRECTORIES already defined warning when running rake from within + the top level directory of an engine that has a test app. + + Fixes #20510 + + *Ersin Akinci* + +* Make enabling or disabling caching in development mode possible with + rake dev:cache. + + Running rake dev:cache will create or remove tmp/caching-dev.txt. When this + file exists config.action_controller.perform_caching will be set to true in + config/environments/development.rb. + + Additionally, a server can be started with either --dev-caching or + --no-dev-caching included to toggle caching on startup. + + *Jussi Mertanen*, *Chuck Callebs* + +* Add a `--api` option in order to generate plugins that can be added + inside an API application. + + *Robin Dupret* + * Fix `NoMethodError` when generating a scaffold inside a full engine. *Yuji Yaginuma* diff --git a/railties/Rakefile b/railties/Rakefile index 4393f45790..cf130a5f14 100644 --- a/railties/Rakefile +++ b/railties/Rakefile @@ -26,7 +26,7 @@ end Rake::TestTask.new('test:regular') do |t| t.libs << 'test' << "#{File.dirname(__FILE__)}/../activesupport/lib" t.pattern = 'test/**/*_test.rb' - t.warning = true + t.warning = false t.verbose = true t.ruby_opts = ["--dev"] if defined?(JRUBY_VERSION) end diff --git a/railties/lib/rails/application/bootstrap.rb b/railties/lib/rails/application/bootstrap.rb index 0f4d932749..9baf8aa742 100644 --- a/railties/lib/rails/application/bootstrap.rb +++ b/railties/lib/rails/application/bootstrap.rb @@ -63,7 +63,7 @@ INFO Rails.cache = ActiveSupport::Cache.lookup_store(config.cache_store) if Rails.cache.respond_to?(:middleware) - config.middleware.insert_before("Rack::Runtime", Rails.cache.middleware) + config.middleware.insert_before(::Rack::Runtime, Rails.cache.middleware) end end end diff --git a/railties/lib/rails/application/finisher.rb b/railties/lib/rails/application/finisher.rb index f8f92792a7..404e3c3e23 100644 --- a/railties/lib/rails/application/finisher.rb +++ b/railties/lib/rails/application/finisher.rb @@ -86,7 +86,7 @@ module Rails # added in the hook are taken into account. initializer :set_clear_dependencies_hook, group: :all do callback = lambda do - ActiveSupport::Dependencies.interlock.attempt_loading do + ActiveSupport::Dependencies.interlock.attempt_unloading do ActiveSupport::DescendantsTracker.clear ActiveSupport::Dependencies.clear end diff --git a/railties/lib/rails/application_controller.rb b/railties/lib/rails/application_controller.rb index 9a29ec21cf..618a09a5b3 100644 --- a/railties/lib/rails/application_controller.rb +++ b/railties/lib/rails/application_controller.rb @@ -6,7 +6,7 @@ class Rails::ApplicationController < ActionController::Base # :nodoc: def require_local! unless local_request? - render text: '<p>For security purposes, this information is only available to local requests.</p>', status: :forbidden + render html: '<p>For security purposes, this information is only available to local requests.</p>'.html_safe, status: :forbidden end end diff --git a/railties/lib/rails/commands/server.rb b/railties/lib/rails/commands/server.rb index d1e445ac70..d3ea441f8e 100644 --- a/railties/lib/rails/commands/server.rb +++ b/railties/lib/rails/commands/server.rb @@ -34,6 +34,9 @@ module Rails opts.on("-P", "--pid=pid", String, "Specifies the PID file.", "Default: tmp/pids/server.pid") { |v| options[:pid] = v } + opts.on("-C", "--[no-]dev-caching", + "Specifies whether to perform caching in development.", + "true or false") { |v| options[:caching] = v } opts.separator "" @@ -67,6 +70,7 @@ module Rails print_boot_information trap(:INT) { exit } create_tmp_directories + setup_dev_caching log_to_stdout if options[:log_stdout] super @@ -82,16 +86,27 @@ module Rails def default_options super.merge({ - Port: 3000, + Port: ENV.fetch('PORT', 3000).to_i, DoNotReverseLookup: true, environment: (ENV['RAILS_ENV'] || ENV['RACK_ENV'] || "development").dup, daemonize: false, + caching: false, pid: File.expand_path("tmp/pids/server.pid") }) end private + def setup_dev_caching + return unless options[:environment] == "development" + + if options[:caching] == false + delete_cache_file + elsif options[:caching] + create_cache_file + end + end + def print_boot_information url = "#{options[:SSLEnable] ? 'https' : 'http'}://#{options[:Host]}:#{options[:Port]}" puts "=> Booting #{ActiveSupport::Inflector.demodulize(server)}" @@ -101,6 +116,14 @@ module Rails puts "=> Ctrl-C to shutdown server" unless options[:daemonize] end + def create_cache_file + FileUtils.touch("tmp/caching-dev.txt") + end + + def delete_cache_file + FileUtils.rm("tmp/caching-dev.txt") if File.exist?("tmp/caching-dev.txt") + end + def create_tmp_directories %w(cache pids sockets).each do |dir_to_make| FileUtils.mkdir_p(File.join(Rails.root, 'tmp', dir_to_make)) diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb index 1dede32dd4..e90d41cbec 100644 --- a/railties/lib/rails/engine.rb +++ b/railties/lib/rails/engine.rb @@ -519,17 +519,15 @@ module Rails # Define the Rack API for this engine. def call(env) env.merge!(env_config) - if env['SCRIPT_NAME'] - env[routes.env_key] = env['SCRIPT_NAME'].dup - end + req = ActionDispatch::Request.new env + req.routes = routes + req.engine_script_name = req.script_name app.call(env) end # Defines additional Rack env configuration that is added on each call. def env_config - @env_config ||= { - 'action_dispatch.routes' => routes - } + @env_config ||= {} end # Defines the routes for this engine. If a block is given to @@ -589,7 +587,7 @@ module Rails # I18n load paths are a special case since the ones added # later have higher priority. initializer :add_locales do - config.i18n.railties_load_path.concat(paths["config/locales"].existent) + config.i18n.railties_load_path << paths["config/locales"] end initializer :add_view_paths do diff --git a/railties/lib/rails/generators.rb b/railties/lib/rails/generators.rb index b430cf1909..2645102619 100644 --- a/railties/lib/rails/generators.rb +++ b/railties/lib/rails/generators.rb @@ -178,7 +178,7 @@ module Rails options = sorted_groups.flat_map(&:last) suggestions = options.sort_by {|suggested| levenshtein_distance(namespace.to_s, suggested) }.first(3) msg = "Could not find generator '#{namespace}'. " - msg << "Maybe you meant #{ suggestions.map {|s| "'#{s}'"}.to_sentence(last_word_connector: " or ") }\n" + msg << "Maybe you meant #{ suggestions.map {|s| "'#{s}'"}.to_sentence(last_word_connector: " or ", locale: :en) }\n" msg << "Run `rails generate --help` for more options." puts msg end diff --git a/railties/lib/rails/generators/actions.rb b/railties/lib/rails/generators/actions.rb index 560a553789..b4356f71e0 100644 --- a/railties/lib/rails/generators/actions.rb +++ b/railties/lib/rails/generators/actions.rb @@ -92,11 +92,11 @@ module Rails # file in <tt>config/environments</tt>. # # environment do - # "config.autoload_paths += %W(#{config.root}/extras)" + # "config.action_controller.asset_host = 'cdn.provider.com'" # end # # environment(nil, env: "development") do - # "config.autoload_paths += %W(#{config.root}/extras)" + # "config.action_controller.asset_host = 'localhost:3000'" # end def environment(data=nil, options={}) sentinel = /class [a-z_:]+ < Rails::Application/i diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb index 249fe96772..38074e80e0 100644 --- a/railties/lib/rails/generators/app_base.rb +++ b/railties/lib/rails/generators/app_base.rb @@ -209,13 +209,19 @@ module Rails [ GemfileEntry.path('rails', Rails::Generators::RAILS_DEV_PATH), GemfileEntry.github('sprockets-rails', 'rails/sprockets-rails'), - GemfileEntry.github('arel', 'rails/arel') + GemfileEntry.github('sprockets', 'rails/sprockets'), + GemfileEntry.github('sass-rails', 'rails/sass-rails'), + GemfileEntry.github('arel', 'rails/arel'), + GemfileEntry.github('rack', 'rack/rack') ] elsif options.edge? [ GemfileEntry.github('rails', 'rails/rails'), GemfileEntry.github('sprockets-rails', 'rails/sprockets-rails'), - GemfileEntry.github('arel', 'rails/arel') + GemfileEntry.github('sprockets', 'rails/sprockets'), + GemfileEntry.github('sass-rails', 'rails/sass-rails'), + GemfileEntry.github('arel', 'rails/arel'), + GemfileEntry.github('rack', 'rack/rack') ] else [GemfileEntry.version('rails', @@ -255,8 +261,6 @@ module Rails return [] if options[:skip_sprockets] gems = [] - gems << GemfileEntry.version('sass-rails', '~> 5.0', - 'Use SCSS for stylesheets') gems << GemfileEntry.version('uglifier', '>= 1.3.0', diff --git a/railties/lib/rails/generators/base.rb b/railties/lib/rails/generators/base.rb index 813b8b629e..6fa413f8b0 100644 --- a/railties/lib/rails/generators/base.rb +++ b/railties/lib/rails/generators/base.rb @@ -103,12 +103,12 @@ module Rails # hook_for :test_framework, as: :controller # end # - # And now it will lookup at: + # And now it will look up at: # # "test_unit:controller", "test_unit" # - # Similarly, if you want it to also lookup in the rails namespace, you just - # need to provide the :in value: + # Similarly, if you want it to also look up in the rails namespace, you + # just need to provide the :in value: # # class AwesomeGenerator < Rails::Generators::Base # hook_for :test_framework, in: :rails, as: :controller 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 c3b8ef1181..5f4904fee1 100644 --- a/railties/lib/rails/generators/erb/scaffold/templates/index.html.erb +++ b/railties/lib/rails/generators/erb/scaffold/templates/index.html.erb @@ -28,4 +28,4 @@ <br> -<%%= link_to 'New <%= human_name %>', new_<%= singular_table_name %>_path %> +<%%= link_to 'New <%= singular_table_name.titleize %>', new_<%= singular_table_name %>_path %> diff --git a/railties/lib/rails/generators/rails/app/templates/Gemfile b/railties/lib/rails/generators/rails/app/templates/Gemfile index b083381255..6a1c2faaab 100644 --- a/railties/lib/rails/generators/rails/app/templates/Gemfile +++ b/railties/lib/rails/generators/rails/app/templates/Gemfile @@ -36,13 +36,15 @@ group :development, :test do end group :development do +<%- unless options.api? -%> # Access an IRB console on exception pages or by using <%%= console %> in views <%- if options.dev? || options.edge? -%> gem 'web-console', github: 'rails/web-console' <%- else -%> gem 'web-console', '~> 2.0' <%- end -%> -<%- if spring_install? %> +<%- end -%> +<% if spring_install? -%> # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring gem 'spring' <% 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 cb86978d4c..c88426ec06 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 @@ -5,7 +5,7 @@ // or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path. // // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the -// compiled file. +// compiled file. JavaScript code in this file should be added after the last require_* statement. // // Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details // about supported directives. diff --git a/railties/lib/rails/generators/rails/app/templates/app/assets/manifest.js.tt b/railties/lib/rails/generators/rails/app/templates/app/assets/manifest.js.tt new file mode 100644 index 0000000000..3325553f57 --- /dev/null +++ b/railties/lib/rails/generators/rails/app/templates/app/assets/manifest.js.tt @@ -0,0 +1,8 @@ + +<% unless options.api? -%> +//= link_tree ./images +<% end -%> +<% unless options.skip_javascript -%> +//= link ./javascripts/application.js +<% end -%> +//= link ./stylesheets/application.css 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 0cdd2788d0..0ebd7fe829 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 @@ -7,7 +7,8 @@ * * 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 other CSS/SCSS - * files in this directory. It is generally better to create a new file per style scope. + * files in this directory. Styles in this file should be added after the last require_* statement. + * It is generally better to create a new file per style scope. * *= require_tree . *= require_self diff --git a/railties/lib/rails/generators/rails/app/templates/bin/setup b/railties/lib/rails/generators/rails/app/templates/bin/setup index 0d41f2fe4c..0c8b179827 100644 --- a/railties/lib/rails/generators/rails/app/templates/bin/setup +++ b/railties/lib/rails/generators/rails/app/templates/bin/setup @@ -5,13 +5,17 @@ include FileUtils # path to your application root. APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) +def system!(*args) + system(*args) || abort("\n== Command #{args} failed ==") +end + chdir APP_ROOT do # This script is a starting point to setup your application. # Add necessary setup steps to this file. puts '== Installing dependencies ==' - system 'gem install bundler --conservative' - system('bundle check') or system('bundle install') + system! 'gem install bundler --conservative' + system('bundle check') or system!('bundle install') # puts "\n== Copying sample files ==" # unless File.exist?('config/database.yml') @@ -19,11 +23,11 @@ chdir APP_ROOT do # end puts "\n== Preparing database ==" - system 'ruby bin/rake db:setup' + system! 'ruby bin/rake db:setup' puts "\n== Removing old logs and tempfiles ==" - system 'ruby bin/rake log:clear tmp:clear' + system! 'ruby bin/rake log:clear tmp:clear' puts "\n== Restarting application server ==" - system 'ruby bin/rake restart' + system! 'ruby bin/rake restart' end diff --git a/railties/lib/rails/generators/rails/app/templates/bin/update b/railties/lib/rails/generators/rails/app/templates/bin/update new file mode 100644 index 0000000000..9830e6b29a --- /dev/null +++ b/railties/lib/rails/generators/rails/app/templates/bin/update @@ -0,0 +1,28 @@ +require 'pathname' +require 'fileutils' +include FileUtils + +# path to your application root. +APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) + +def system!(*args) + system(*args) || abort("\n== Command #{args} failed ==") +end + +chdir APP_ROOT do + # This script is a way to update your development environment automatically. + # Add necessary update steps to this file. + + puts '== Installing dependencies ==' + system! 'gem install bundler --conservative' + system 'bundle check' or system! 'bundle install' + + puts "\n== Updating database ==" + system! 'bin/rake db:migrate' + + puts "\n== Removing old logs and tempfiles ==" + system! 'bin/rake log:clear tmp:clear' + + puts "\n== Restarting application server ==" + system! 'bin/rake restart' +end 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 ecb5d4170f..e29f0bacaa 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 @@ -9,9 +9,19 @@ Rails.application.configure do # Do not eager load code on boot. config.eager_load = false - # Show full error reports and disable caching. + # Show full error reports. config.consider_all_requests_local = true - config.action_controller.perform_caching = false + + # Enable/disable caching. By default caching is disabled. + if Rails.root.join('tmp/caching-dev.txt').exist? + config.action_controller.perform_caching = true + config.static_cache_control = "public, max-age=172800" + config.cache_store = :memory_store + else + config.action_controller.perform_caching = false + config.cache_store = :null_store + end + <%- unless options.skip_action_mailer? -%> # Don't care if the mailer can't send. diff --git a/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt index 8c09396fc1..0297ab75f6 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 @@ -51,7 +51,8 @@ Rails.application.configure do # config.log_tags = [ :subdomain, :request_id ] # Use a different logger for distributed setups. - # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new) + # require 'syslog/logger' + # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name') # Use a different cache store in production. # config.cache_store = :mem_cache_store 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 3f66539d54..787824f888 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/routes.rb +++ b/railties/lib/rails/generators/rails/app/templates/config/routes.rb @@ -1,56 +1,3 @@ Rails.application.routes.draw do - # The priority is based upon order of creation: first created -> highest priority. - # See how all your routes lay out with "rake routes". - - # You can have the root of your site routed with "root" - # root 'welcome#index' - - # Example of regular route: - # get 'products/:id' => 'catalog#view' - - # Example of named route that can be invoked with purchase_url(id: product.id) - # get 'products/:id/purchase' => 'catalog#purchase', as: :purchase - - # Example resource route (maps HTTP verbs to controller actions automatically): - # resources :products - - # Example resource route with options: - # resources :products do - # member do - # get 'short' - # post 'toggle' - # end - # - # collection do - # get 'sold' - # end - # end - - # Example resource route with sub-resources: - # resources :products do - # resources :comments, :sales - # resource :seller - # end - - # Example resource route with more complex sub-resources: - # resources :products do - # resources :comments - # resources :sales do - # get 'recent', on: :collection - # end - # end - - # Example resource route with concerns: - # concern :toggleable do - # post 'toggle' - # end - # resources :posts, concerns: :toggleable - # resources :photos, concerns: :toggleable - - # Example resource route within a namespace: - # namespace :admin do - # # Directs /admin/products/* to Admin::ProductsController - # # (app/controllers/admin/products_controller.rb) - # resources :products - # end + # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html end diff --git a/railties/lib/rails/generators/rails/plugin/plugin_generator.rb b/railties/lib/rails/generators/rails/plugin/plugin_generator.rb index 66111004aa..8fea30189e 100644 --- a/railties/lib/rails/generators/rails/plugin/plugin_generator.rb +++ b/railties/lib/rails/generators/rails/plugin/plugin_generator.rb @@ -17,15 +17,22 @@ module Rails def app if mountable? - directory 'app' - empty_directory_with_keep_file "app/assets/images/#{namespaced_name}" + if api? + directory 'app', exclude_pattern: %r{app/(views|helpers)} + else + directory 'app' + empty_directory_with_keep_file "app/assets/images/#{namespaced_name}" + end elsif full? empty_directory_with_keep_file 'app/models' empty_directory_with_keep_file 'app/controllers' - empty_directory_with_keep_file 'app/views' - empty_directory_with_keep_file 'app/helpers' empty_directory_with_keep_file 'app/mailers' - empty_directory_with_keep_file "app/assets/images/#{namespaced_name}" + + unless api? + empty_directory_with_keep_file "app/assets/images/#{namespaced_name}" + empty_directory_with_keep_file 'app/helpers' + empty_directory_with_keep_file 'app/views' + end end end @@ -82,6 +89,7 @@ task default: :test opts = (options || {}).slice(*PASSTHROUGH_OPTIONS) opts[:force] = force opts[:skip_bundle] = true + opts[:api] = options.api? invoke Rails::Generators::AppGenerator, [ File.expand_path(dummy_path, destination_root) ], opts @@ -96,8 +104,9 @@ task default: :test end def test_dummy_assets - template "rails/javascripts.js", "#{dummy_path}/app/assets/javascripts/application.js", force: true - template "rails/stylesheets.css", "#{dummy_path}/app/assets/stylesheets/application.css", force: true + template "rails/javascripts.js", "#{dummy_path}/app/assets/javascripts/application.js", force: true + template "rails/stylesheets.css", "#{dummy_path}/app/assets/stylesheets/application.css", force: true + template "rails/dummy_manifest.js", "#{dummy_path}/app/assets/manifest.js", force: true end def test_dummy_clean @@ -114,6 +123,10 @@ task default: :test end end + def assets_manifest + template "rails/engine_manifest.js", "app/assets/#{underscored_name}_manifest.js" + end + def stylesheets if mountable? copy_file "rails/stylesheets.css", @@ -176,6 +189,9 @@ task default: :test desc: "If creating plugin in application's directory " + "skip adding entry to Gemfile" + class_option :api, type: :boolean, default: false, + desc: "Generate a smaller stack for API application plugins" + def initialize(*args) @dummy_path = nil super @@ -209,16 +225,20 @@ task default: :test build(:lib) end + def create_assets_manifest_file + build(:assets_manifest) unless api? + end + def create_public_stylesheets_files - build(:stylesheets) + build(:stylesheets) unless api? end def create_javascript_files - build(:javascripts) + build(:javascripts) unless api? end def create_images_directory - build(:images) + build(:images) unless api? end def create_bin_files @@ -305,6 +325,10 @@ task default: :test options[:skip_test].blank? || options[:dummy_path] != 'test/dummy' end + def api? + options[:api] + end + def self.banner "rails plugin new #{self.arguments.map(&:usage).join(' ')} [options]" end diff --git a/railties/lib/rails/generators/rails/plugin/templates/app/controllers/%namespaced_name%/application_controller.rb.tt b/railties/lib/rails/generators/rails/plugin/templates/app/controllers/%namespaced_name%/application_controller.rb.tt index 7157e48c42..7fe4e5034d 100644 --- a/railties/lib/rails/generators/rails/plugin/templates/app/controllers/%namespaced_name%/application_controller.rb.tt +++ b/railties/lib/rails/generators/rails/plugin/templates/app/controllers/%namespaced_name%/application_controller.rb.tt @@ -1,5 +1,5 @@ <%= wrap_in_modules <<-rb.strip_heredoc - class ApplicationController < ActionController::Base + class ApplicationController < ActionController::#{api? ? "API" : "Base"} end rb %> diff --git a/railties/lib/rails/generators/rails/plugin/templates/lib/%namespaced_name%/engine.rb b/railties/lib/rails/generators/rails/plugin/templates/lib/%namespaced_name%/engine.rb index 17afd52177..8938770fc4 100644 --- a/railties/lib/rails/generators/rails/plugin/templates/lib/%namespaced_name%/engine.rb +++ b/railties/lib/rails/generators/rails/plugin/templates/lib/%namespaced_name%/engine.rb @@ -1,6 +1,7 @@ <%= wrap_in_modules <<-rb.strip_heredoc class Engine < ::Rails::Engine #{mountable? ? ' isolate_namespace ' + camelized_modules : ' '} + #{api? ? " config.generators.api_only = true" : ' '} end rb %> diff --git a/railties/lib/rails/generators/rails/plugin/templates/lib/%namespaced_name%/version.rb b/railties/lib/rails/generators/rails/plugin/templates/lib/%namespaced_name%/version.rb index d257295988..b08f4ef9ae 100644 --- a/railties/lib/rails/generators/rails/plugin/templates/lib/%namespaced_name%/version.rb +++ b/railties/lib/rails/generators/rails/plugin/templates/lib/%namespaced_name%/version.rb @@ -1 +1 @@ -<%= wrap_in_modules 'VERSION = "0.0.1"' %> +<%= wrap_in_modules "VERSION = '0.1.0'" %> diff --git a/railties/lib/rails/generators/rails/plugin/templates/rails/dummy_manifest.js b/railties/lib/rails/generators/rails/plugin/templates/rails/dummy_manifest.js new file mode 100644 index 0000000000..ace695a811 --- /dev/null +++ b/railties/lib/rails/generators/rails/plugin/templates/rails/dummy_manifest.js @@ -0,0 +1,11 @@ + +<% unless api? -%> +//= link_tree ./images +<% end -%> +<% unless options.skip_javascript -%> +//= link ./javascripts/application.js +<% end -%> +//= link ./stylesheets/application.css +<% if mountable? && !api? -%> +//= link <%= underscored_name %>_manifest.js +<% end -%> diff --git a/railties/lib/rails/generators/rails/plugin/templates/rails/engine_manifest.js b/railties/lib/rails/generators/rails/plugin/templates/rails/engine_manifest.js new file mode 100644 index 0000000000..f8ef26982a --- /dev/null +++ b/railties/lib/rails/generators/rails/plugin/templates/rails/engine_manifest.js @@ -0,0 +1,6 @@ +<% if mountable? -%> +<% unless options.skip_javascript -%> +//= link ./javascripts/<%= namespaced_name %>/application.js +<% end -%> +//= link ./stylesheets/<%= namespaced_name %>/application.css +<% end -%> diff --git a/railties/lib/rails/generators/rails/plugin/templates/rails/javascripts.js b/railties/lib/rails/generators/rails/plugin/templates/rails/javascripts.js index 8913b40f69..e54c6461cc 100644 --- a/railties/lib/rails/generators/rails/plugin/templates/rails/javascripts.js +++ b/railties/lib/rails/generators/rails/plugin/templates/rails/javascripts.js @@ -5,7 +5,7 @@ // or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path. // // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the -// compiled file. +// compiled file. JavaScript code in this file should be added after the last require_* statement. // // Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details // about supported directives. diff --git a/railties/lib/rails/generators/rails/plugin/templates/rails/stylesheets.css b/railties/lib/rails/generators/rails/plugin/templates/rails/stylesheets.css index 0cdd2788d0..0ebd7fe829 100644 --- a/railties/lib/rails/generators/rails/plugin/templates/rails/stylesheets.css +++ b/railties/lib/rails/generators/rails/plugin/templates/rails/stylesheets.css @@ -7,7 +7,8 @@ * * 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 other CSS/SCSS - * files in this directory. It is generally better to create a new file per style scope. + * files in this directory. Styles in this file should be added after the last require_* statement. + * It is generally better to create a new file per style scope. * *= require_tree . *= require_self diff --git a/railties/lib/rails/generators/rails/plugin/templates/test/test_helper.rb b/railties/lib/rails/generators/rails/plugin/templates/test/test_helper.rb index 95adcc06ff..f315144723 100644 --- a/railties/lib/rails/generators/rails/plugin/templates/test/test_helper.rb +++ b/railties/lib/rails/generators/rails/plugin/templates/test/test_helper.rb @@ -14,12 +14,10 @@ require "rails/test_help" # to be shown. Minitest.backtrace_filter = Minitest::BacktraceFilter.new -# Load support files -Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f } - # Load fixtures from the engine if ActiveSupport::TestCase.respond_to?(:fixture_path=) ActiveSupport::TestCase.fixture_path = File.expand_path("../fixtures", __FILE__) + ActionDispatch::IntegrationTest.fixture_path = ActiveSupport::TestCase.fixture_path ActiveSupport::TestCase.file_fixture_path = ActiveSupport::TestCase.fixture_path + "/files" ActiveSupport::TestCase.fixtures :all end diff --git a/railties/lib/rails/generators/test_unit/scaffold/templates/api_functional_test.rb b/railties/lib/rails/generators/test_unit/scaffold/templates/api_functional_test.rb index 896b38bc8f..f302cd6c3d 100644 --- a/railties/lib/rails/generators/test_unit/scaffold/templates/api_functional_test.rb +++ b/railties/lib/rails/generators/test_unit/scaffold/templates/api_functional_test.rb @@ -3,7 +3,10 @@ require 'test_helper' <% module_namespacing do -%> class <%= controller_class_name %>ControllerTest < ActionController::TestCase setup do - @<%= singular_table_name %> = <%= table_name %>(:one) + @<%= singular_table_name %> = <%= fixture_name %>(:one) +<% if mountable_engine? -%> + @routes = Engine.routes +<% end -%> end test "should get index" do diff --git a/railties/lib/rails/mailers_controller.rb b/railties/lib/rails/mailers_controller.rb index 41422a656c..78a857e0f1 100644 --- a/railties/lib/rails/mailers_controller.rb +++ b/railties/lib/rails/mailers_controller.rb @@ -26,7 +26,7 @@ class Rails::MailersController < Rails::ApplicationController # :nodoc: if part = find_part(part_type) response.content_type = part_type - render text: part.respond_to?(:decoded) ? part.decoded : part + render plain: part.respond_to?(:decoded) ? part.decoded : part else raise AbstractController::ActionNotFound, "Email part '#{part_type}' not found in #{@preview.name}##{@email_action}" end diff --git a/railties/lib/rails/paths.rb b/railties/lib/rails/paths.rb index ebcaaaba46..e47616a87f 100644 --- a/railties/lib/rails/paths.rb +++ b/railties/lib/rails/paths.rb @@ -123,6 +123,10 @@ module Rails options[:load_path] ? load_path! : skip_load_path! end + def absolute_current # :nodoc: + File.expand_path(@current, @root.path) + end + def children keys = @root.keys.find_all { |k| k.start_with?(@current) && k != @current @@ -175,6 +179,10 @@ module Rails @paths end + def extensions # :nodoc: + $1.split(',') if @glob =~ /\{([\S]+)\}/ + end + # Expands all paths against the root and return all unique values. def expanded raise "You need to set a path root" unless @root.path diff --git a/railties/lib/rails/source_annotation_extractor.rb b/railties/lib/rails/source_annotation_extractor.rb index 9b058a1848..8dd87b6cc5 100644 --- a/railties/lib/rails/source_annotation_extractor.rb +++ b/railties/lib/rails/source_annotation_extractor.rb @@ -3,7 +3,7 @@ # rake notes # rake notes:optimize # -# and friends. See <tt>rake -T notes</tt> and <tt>railties/lib/tasks/annotations.rake</tt>. +# and friends. See <tt>rake -T notes</tt> and <tt>railties/lib/rails/tasks/annotations.rake</tt>. # # Annotation objects are triplets <tt>:line</tt>, <tt>:tag</tt>, <tt>:text</tt> that # represent the line where the annotation lives, its tag, and its text. Note diff --git a/railties/lib/rails/tasks.rb b/railties/lib/rails/tasks.rb index 2c3d278eca..d3e33584d7 100644 --- a/railties/lib/rails/tasks.rb +++ b/railties/lib/rails/tasks.rb @@ -3,6 +3,7 @@ require 'rake' # Load Rails Rakefile extensions %w( annotations + dev framework initializers log @@ -10,8 +11,9 @@ require 'rake' misc restart routes - statistics tmp -).each do |task| +).tap { |arr| + arr << 'statistics' if Rake.application.current_scope.empty? +}.each do |task| load "rails/tasks/#{task}.rake" end diff --git a/railties/lib/rails/tasks/dev.rake b/railties/lib/rails/tasks/dev.rake new file mode 100644 index 0000000000..e949172d3f --- /dev/null +++ b/railties/lib/rails/tasks/dev.rake @@ -0,0 +1,15 @@ +namespace :dev do + task :cache do + desc 'Toggle development mode caching on/off' + + if File.exist? 'tmp/caching-dev.txt' + File.delete 'tmp/caching-dev.txt' + puts 'Development mode is no longer being cached.' + else + FileUtils.touch 'tmp/caching-dev.txt' + puts 'Development mode is now being cached.' + end + + FileUtils.touch 'tmp/restart.txt' + end +end diff --git a/railties/lib/rails/tasks/engine.rake b/railties/lib/rails/tasks/engine.rake index 16ad1bfc84..c51524f8f6 100644 --- a/railties/lib/rails/tasks/engine.rake +++ b/railties/lib/rails/tasks/engine.rake @@ -40,7 +40,7 @@ namespace :db do desc "Rolls the schema back to the previous version (specify steps w/ STEP=n)." app_task "rollback" - desc "Create a db/schema.rb file that can be portably used against any DB supported by AR" + desc "Create a db/schema.rb file that can be portably used against any DB supported by Active Record" app_task "schema:dump" desc "Load a schema.rb file into the database" diff --git a/railties/lib/rails/test_help.rb b/railties/lib/rails/test_help.rb index 828039dc43..5cc1b5b219 100644 --- a/railties/lib/rails/test_help.rb +++ b/railties/lib/rails/test_help.rb @@ -28,14 +28,14 @@ if defined?(ActiveRecord::Base) end class ActionController::TestCase - def before_setup + def before_setup # :nodoc: @routes = Rails.application.routes super end end class ActionDispatch::IntegrationTest - def before_setup + def before_setup # :nodoc: @routes = Rails.application.routes super end diff --git a/railties/lib/rails/test_unit/minitest_plugin.rb b/railties/lib/rails/test_unit/minitest_plugin.rb index ab71298509..dacab08ec3 100644 --- a/railties/lib/rails/test_unit/minitest_plugin.rb +++ b/railties/lib/rails/test_unit/minitest_plugin.rb @@ -16,7 +16,7 @@ module Minitest opts.separator "" opts.separator "Rails options:" - opts.on("-e", "--environment [ENV]", + opts.on("-e", "--environment ENV", "Run tests in the ENV environment") do |env| options[:environment] = env.strip end @@ -29,12 +29,21 @@ module Minitest options[:patterns] = opts.order! end + # Running several Rake tasks in a single command would trip up the runner, + # as the patterns would also contain the other Rake tasks. + def self.rake_run(patterns) # :nodoc: + @rake_patterns = patterns + run + end + def self.plugin_rails_init(options) self.run_with_rails_extension = true ENV["RAILS_ENV"] = options[:environment] || "test" - ::Rails::TestRequirer.require_files options[:patterns] unless run_with_autorun + unless run_with_autorun + ::Rails::TestRequirer.require_files @rake_patterns || options[:patterns] + end unless options[:full_backtrace] || ENV["BACKTRACE"] # Plugin can run without Rails loaded, check before filtering. @@ -48,4 +57,5 @@ module Minitest mattr_accessor(:run_with_rails_extension) { false } end +Minitest.load_plugins Minitest.extensions << 'rails' diff --git a/railties/lib/rails/test_unit/test_requirer.rb b/railties/lib/rails/test_unit/test_requirer.rb index 84c2256729..83d2c55ffd 100644 --- a/railties/lib/rails/test_unit/test_requirer.rb +++ b/railties/lib/rails/test_unit/test_requirer.rb @@ -18,7 +18,7 @@ module Rails arg = arg.gsub(/:(\d+)?$/, '') if Dir.exist?(arg) "#{arg}/**/*_test.rb" - elsif File.file?(arg) + else arg end end diff --git a/railties/lib/rails/test_unit/testing.rake b/railties/lib/rails/test_unit/testing.rake index dda492f974..6676c6a079 100644 --- a/railties/lib/rails/test_unit/testing.rake +++ b/railties/lib/rails/test_unit/testing.rake @@ -7,7 +7,7 @@ task default: :test desc "Runs all tests in test folder" task :test do $: << "test" - Minitest.run(['test']) + Minitest.rake_run(["test"]) end namespace :test do @@ -24,22 +24,22 @@ namespace :test do ["models", "helpers", "controllers", "mailers", "integration", "jobs"].each do |name| task name => "test:prepare" do $: << "test" - Minitest.run(["test/#{name}"]) + Minitest.rake_run(["test/#{name}"]) end end task :generators => "test:prepare" do $: << "test" - Minitest.run(["test/lib/generators"]) + Minitest.rake_run(["test/lib/generators"]) end task :units => "test:prepare" do $: << "test" - Minitest.run(["test/models", "test/helpers", "test/unit"]) + Minitest.rake_run(["test/models", "test/helpers", "test/unit"]) end task :functionals => "test:prepare" do $: << "test" - Minitest.run(["test/controllers", "test/mailers", "test/functional"]) + Minitest.rake_run(["test/controllers", "test/mailers", "test/functional"]) end end diff --git a/railties/railties.gemspec b/railties/railties.gemspec index afe1603448..a06336f698 100644 --- a/railties/railties.gemspec +++ b/railties/railties.gemspec @@ -15,7 +15,7 @@ Gem::Specification.new do |s| s.email = 'david@loudthinking.com' s.homepage = 'http://www.rubyonrails.org' - s.files = Dir['CHANGELOG.md', 'README.rdoc', 'RDOC_MAIN.rdoc', 'exe/**/*', 'lib/**/{*,.[a-z]*}'] + s.files = Dir['CHANGELOG.md', 'README.rdoc', 'MIT-LICENSE', 'RDOC_MAIN.rdoc', 'exe/**/*', 'lib/**/{*,.[a-z]*}'] s.require_path = 'lib' s.bindir = 'exe' diff --git a/railties/test/application/asset_debugging_test.rb b/railties/test/application/asset_debugging_test.rb index 36ab8109a7..fef65adda2 100644 --- a/railties/test/application/asset_debugging_test.rb +++ b/railties/test/application/asset_debugging_test.rb @@ -48,7 +48,7 @@ module ApplicationTests assert_no_match(/<script src="\/assets\/xmlhr-([0-z]+)\.js"><\/script>/, last_response.body) end - test "assets aren't concatenated when compile is true is on and debug_assets params is true" do + test "assets are served with sourcemaps when compile is true and debug_assets params is true" do add_to_env_config "production", "config.assets.compile = true" ENV["RAILS_ENV"] = "production" @@ -57,8 +57,7 @@ module ApplicationTests class ::PostsController < ActionController::Base ; end get '/posts?debug_assets=true' - assert_match(/<script src="\/assets\/application(\.self)?-([0-z]+)\.js\?body=1"><\/script>/, last_response.body) - assert_match(/<script src="\/assets\/xmlhr(\.self)?-([0-z]+)\.js\?body=1"><\/script>/, last_response.body) + assert_match(/<script src="\/assets\/application(\.debug)?-([0-z]+)\.js"><\/script>/, last_response.body) end end end diff --git a/railties/test/application/assets_test.rb b/railties/test/application/assets_test.rb index 6952472ff5..ddcd51f3fc 100644 --- a/railties/test/application/assets_test.rb +++ b/railties/test/application/assets_test.rb @@ -60,6 +60,7 @@ module ApplicationTests test "assets do not require compressors until it is used" do app_file "app/assets/javascripts/demo.js.erb", "<%= :alert %>();" add_to_env_config "production", "config.assets.compile = true" + add_to_env_config "production", "config.assets.precompile = []" ENV["RAILS_ENV"] = "production" require "#{app_path}/config/environment" @@ -71,6 +72,7 @@ module ApplicationTests end test "precompile creates the file, gives it the original asset's content and run in production as default" do + app_file "app/assets/manifest.js", "//= link_tree ./javascripts" app_file "app/assets/javascripts/application.js", "alert();" app_file "app/assets/javascripts/foo/application.js", "alert();" @@ -86,6 +88,7 @@ module ApplicationTests end def test_precompile_does_not_hit_the_database + app_file "app/assets/manifest.js", "//= link_tree ./javascripts" app_file "app/assets/javascripts/application.js", "alert();" app_file "app/assets/javascripts/foo/application.js", "alert();" app_file "app/controllers/users_controller.rb", <<-eoruby @@ -177,8 +180,11 @@ module ApplicationTests end test 'precompile use assets defined in app config and reassigned in app env config' do - add_to_config 'config.assets.precompile = [ "something.js" ]' - add_to_env_config 'production', 'config.assets.precompile += [ "another.js" ]' + add_to_config 'config.assets.precompile = [ "something_manifest.js" ]' + add_to_env_config 'production', 'config.assets.precompile += [ "another_manifest.js" ]' + + app_file 'app/assets/something_manifest.js', '//= link ./javascripts/something.js' + app_file 'app/assets/another_manifest.js', '//= link ./javascripts/another.js' app_file 'app/assets/javascripts/something.js.erb', 'alert();' app_file 'app/assets/javascripts/another.js.erb', 'alert();' @@ -189,14 +195,14 @@ module ApplicationTests assert_file_exists("#{app_path}/public/assets/another-*.js") end - test "asset pipeline should use a Sprockets::Index when config.assets.digest is true" do + test "asset pipeline should use a Sprockets::CachedEnvironment when config.assets.digest is true" do add_to_config "config.action_controller.perform_caching = false" add_to_env_config "production", "config.assets.compile = true" ENV["RAILS_ENV"] = "production" require "#{app_path}/config/environment" - assert_equal Sprockets::Index, Rails.application.assets.class + assert_equal Sprockets::CachedEnvironment, Rails.application.assets.class end test "precompile creates a manifest file with all the assets listed" do @@ -245,7 +251,7 @@ module ApplicationTests test "precompile properly refers files referenced with asset_path and runs in the provided RAILS_ENV" do app_file "app/assets/images/rails.png", "notactuallyapng" - app_file "app/assets/stylesheets/application.css.erb", "<%= asset_path('rails.png') %>" + app_file "app/assets/stylesheets/application.css.erb", "p { background-image: url(<%= asset_path('rails.png') %>) }" add_to_env_config "test", "config.assets.digest = true" precompile!('RAILS_ENV=test') @@ -257,7 +263,7 @@ module ApplicationTests test "precompile shouldn't use the digests present in manifest.json" do app_file "app/assets/images/rails.png", "notactuallyapng" - app_file "app/assets/stylesheets/application.css.erb", "p { url: <%= asset_path('rails.png') %> }" + app_file "app/assets/stylesheets/application.css.erb", "p { background-image: url(<%= asset_path('rails.png') %>) }" ENV["RAILS_ENV"] = "production" precompile! @@ -276,7 +282,7 @@ module ApplicationTests test "precompile appends the md5 hash to files referenced with asset_path and run in production with digest true" do app_file "app/assets/images/rails.png", "notactuallyapng" - app_file "app/assets/stylesheets/application.css.erb", "<%= asset_path('rails.png') %>" + app_file "app/assets/stylesheets/application.css.erb", "p { background-image: url(<%= asset_path('rails.png') %>) }" ENV["RAILS_ENV"] = "production" precompile! @@ -288,7 +294,8 @@ module ApplicationTests test "precompile should handle utf8 filenames" do filename = "レイルズ.png" app_file "app/assets/images/#{filename}", "not an image really" - add_to_config "config.assets.precompile = [ /\.png$/, /application.(css|js)$/ ]" + app_file "app/assets/manifest.js", "//= link_tree ./images" + add_to_config "config.assets.precompile = %w(manifest.js)" precompile! @@ -393,7 +400,7 @@ module ApplicationTests app_file "app/assets/javascripts/xmlhr.js.erb", "<%= Post.name %>" precompile! - assert_equal "Post;\n", File.read(Dir["#{app_path}/public/assets/application-*.js"].first) + assert_equal "Post\n;\n", File.read(Dir["#{app_path}/public/assets/application-*.js"].first) end test "initialization on the assets group should set assets_dir" do @@ -438,9 +445,9 @@ module ApplicationTests class ::PostsController < ActionController::Base; end get '/posts', {}, {'HTTPS'=>'off'} - assert_match('src="http://example.com/assets/application.self.js', last_response.body) + assert_match('src="http://example.com/assets/application.debug.js', last_response.body) get '/posts', {}, {'HTTPS'=>'on'} - assert_match('src="https://example.com/assets/application.self.js', last_response.body) + assert_match('src="https://example.com/assets/application.debug.js', last_response.body) end test "asset urls should be protocol-relative if no request is in scope" do diff --git a/railties/test/application/initializers/frameworks_test.rb b/railties/test/application/initializers/frameworks_test.rb index 7bba910b9e..6e3707cc27 100644 --- a/railties/test/application/initializers/frameworks_test.rb +++ b/railties/test/application/initializers/frameworks_test.rb @@ -1,5 +1,4 @@ require "isolation/abstract_unit" -require 'set' module ApplicationTests class FrameworksTest < ActiveSupport::TestCase diff --git a/railties/test/application/initializers/i18n_test.rb b/railties/test/application/initializers/i18n_test.rb index 9ee54796a4..ab7f29b0f2 100644 --- a/railties/test/application/initializers/i18n_test.rb +++ b/railties/test/application/initializers/i18n_test.rb @@ -132,6 +132,79 @@ en: assert_equal "2", last_response.body end + test "new locale files are loaded" do + add_to_config <<-RUBY + config.cache_classes = false + RUBY + + app_file "config/locales/en.yml", <<-YAML +en: + foo: "1" + YAML + + app_file 'config/routes.rb', <<-RUBY + Rails.application.routes.draw do + get '/i18n', :to => lambda { |env| [200, {}, [I18n.t(:foo)]] } + end + RUBY + + require 'rack/test' + extend Rack::Test::Methods + load_app + + get "/i18n" + assert_equal "1", last_response.body + + # Wait a full second so we have time for changes to propagate + sleep(1) + + remove_file "config/locales/en.yml" + app_file "config/locales/custom.en.yml", <<-YAML +en: + foo: "2" + YAML + + get "/i18n" + assert_equal "2", last_response.body + end + + test "I18n.load_path is reloaded" do + add_to_config <<-RUBY + config.cache_classes = false + RUBY + + app_file "config/locales/en.yml", <<-YAML +en: + foo: "1" + YAML + + app_file 'config/routes.rb', <<-RUBY + Rails.application.routes.draw do + get '/i18n', :to => lambda { |env| [200, {}, [I18n.load_path.inspect]] } + end + RUBY + + require 'rack/test' + extend Rack::Test::Methods + load_app + + get "/i18n" + + assert_match "en.yml", last_response.body + + # Wait a full second so we have time for changes to propagate + sleep(1) + + app_file "config/locales/fr.yml", <<-YAML +fr: + foo: "2" + YAML + + get "/i18n" + assert_match "fr.yml", last_response.body + assert_match "en.yml", last_response.body + end + # Fallbacks test "not using config.i18n.fallbacks does not initialize I18n.fallbacks" do I18n.backend = Class.new(I18n::Backend::Simple).new diff --git a/railties/test/application/per_request_digest_cache_test.rb b/railties/test/application/per_request_digest_cache_test.rb new file mode 100644 index 0000000000..3198e12662 --- /dev/null +++ b/railties/test/application/per_request_digest_cache_test.rb @@ -0,0 +1,63 @@ +require 'isolation/abstract_unit' +require 'rack/test' +require 'minitest/mock' + +require 'action_view' +require 'active_support/testing/method_call_assertions' + +class PerRequestDigestCacheTest < ActiveSupport::TestCase + include ActiveSupport::Testing::Isolation + include ActiveSupport::Testing::MethodCallAssertions + include Rack::Test::Methods + + setup do + build_app + add_to_config 'config.consider_all_requests_local = true' + + app_file 'app/models/customer.rb', <<-RUBY + class Customer < Struct.new(:name, :id) + extend ActiveModel::Naming + include ActiveModel::Conversion + end + RUBY + + app_file 'config/routes.rb', <<-RUBY + Rails.application.routes.draw do + resources :customers, only: :index + end + RUBY + + app_file 'app/controllers/customers_controller.rb', <<-RUBY + class CustomersController < ApplicationController + def index + render [ Customer.new('david', 1), Customer.new('dingus', 2) ] + end + end + RUBY + + app_file 'app/views/customers/_customer.html.erb', <<-RUBY + <% cache customer do %> + <%= customer.name %> + <% end %> + RUBY + + require "#{app_path}/config/environment" + end + + teardown :teardown_app + + test "digests are reused when rendering the same template twice" do + get '/customers' + assert_equal 200, last_response.status + + assert_equal [ '8ba099b7749542fe765ff34a6824d548' ], ActionView::Digestor.cache.values + assert_equal %w(david dingus), last_response.body.split.map(&:strip) + end + + test "template digests are cleared before a request" do + assert_called(ActionView::Digestor.cache, :clear) do + get '/customers' + assert_equal 200, last_response.status + end + end +end diff --git a/railties/test/application/rake/dev_test.rb b/railties/test/application/rake/dev_test.rb new file mode 100644 index 0000000000..28d8b22a37 --- /dev/null +++ b/railties/test/application/rake/dev_test.rb @@ -0,0 +1,35 @@ +require 'isolation/abstract_unit' + +module ApplicationTests + module RakeTests + class RakeDevTest < ActiveSupport::TestCase + include ActiveSupport::Testing::Isolation + + def setup + build_app + boot_rails + end + + def teardown + teardown_app + end + + test 'dev:cache creates file and outputs message' do + Dir.chdir(app_path) do + output = `rake dev:cache` + assert File.exist?('tmp/caching-dev.txt') + assert_match(/Development mode is now being cached/, output) + end + end + + test 'dev:cache deletes file and outputs message' do + Dir.chdir(app_path) do + output = `rake dev:cache` + output = `rake dev:cache` + assert_not File.exist?('tmp/caching-dev.txt') + assert_match(/Development mode is no longer being cached/, output) + end + end + end + end +end diff --git a/railties/test/application/rake/notes_test.rb b/railties/test/application/rake/notes_test.rb index d6f5fee5c3..c87515f00f 100644 --- a/railties/test/application/rake/notes_test.rb +++ b/railties/test/application/rake/notes_test.rb @@ -114,6 +114,7 @@ module ApplicationTests end test 'register a new extension' do + add_to_config "config.assets.precompile = []" add_to_config %q{ config.annotations.register_extensions("scss", "sass") { |annotation| /\/\/\s*(#{annotation}):?\s*(.*)$/ } } app_file "app/assets/stylesheets/application.css.scss", "// TODO: note in scss" app_file "app/assets/stylesheets/application.css.sass", "// TODO: note in sass" diff --git a/railties/test/application/test_runner_test.rb b/railties/test/application/test_runner_test.rb index 494e6dd7bd..2d47a31826 100644 --- a/railties/test/application/test_runner_test.rb +++ b/railties/test/application/test_runner_test.rb @@ -340,6 +340,11 @@ module ApplicationTests assert_match '0 runs, 0 assertions', run_test_command('') end + def test_raise_error_when_specified_file_does_not_exist + error = capture(:stderr) { run_test_command('test/not_exists.rb') } + assert_match(%r{cannot load such file.+test/not_exists\.rb}, error) + end + private def run_test_command(arguments = 'test/unit/test_test.rb') Dir.chdir(app_path) { `bin/rails t #{arguments}` } diff --git a/railties/test/commands/server_test.rb b/railties/test/commands/server_test.rb index ba688f1e9e..3be4a74f74 100644 --- a/railties/test/commands/server_test.rb +++ b/railties/test/commands/server_test.rb @@ -44,6 +44,29 @@ class Rails::ServerTest < ActiveSupport::TestCase end end + def test_environment_with_port + switch_env "PORT", "1234" do + server = Rails::Server.new + assert_equal 1234, server.options[:Port] + end + end + + def test_caching_without_option + args = [] + options = Rails::Server::Options.new.parse!(args) + assert_equal nil, options[:caching] + end + + def test_caching_with_option + args = ["--dev-caching"] + options = Rails::Server::Options.new.parse!(args) + assert_equal true, options[:caching] + + args = ["--no-dev-caching"] + options = Rails::Server::Options.new.parse!(args) + assert_equal false, options[:caching] + end + def test_log_stdout with_rack_env nil do with_rails_env nil do diff --git a/railties/test/generators/actions_test.rb b/railties/test/generators/actions_test.rb index 2857dae07e..fabba555ef 100644 --- a/railties/test/generators/actions_test.rb +++ b/railties/test/generators/actions_test.rb @@ -1,7 +1,6 @@ require 'generators/generators_test_helper' require 'rails/generators/rails/app/app_generator' require 'env_helpers' -require 'minitest/mock' class ActionsTest < Rails::Generators::TestCase include GeneratorsTestHelper @@ -12,13 +11,11 @@ class ActionsTest < Rails::Generators::TestCase def setup Rails.application = TestApp::Application - @mock_generator = Minitest::Mock.new super end def teardown Rails.application = TestApp::Application.instance - @mock_generator.verify end def test_invoke_other_generator_with_shortcut @@ -150,16 +147,13 @@ class ActionsTest < Rails::Generators::TestCase end def test_git_with_symbol_should_run_command_using_git_scm - @mock_generator.expect(:call, nil, ['git init']) - generator.stub(:run, @mock_generator) do + assert_called_with(generator, :run, ['git init']) do action :git, :init end end def test_git_with_hash_should_run_each_command_using_git_scm - @mock_generator.expect(:call, nil, ["git rm README"]) - @mock_generator.expect(:call, nil, ["git add ."]) - generator.stub(:run, @mock_generator) do + assert_called_with(generator, :run, [ ["git rm README"], ["git add ."] ]) do action :git, rm: 'README', add: '.' end end @@ -185,15 +179,13 @@ class ActionsTest < Rails::Generators::TestCase end def test_generate_should_run_script_generate_with_argument_and_options - @mock_generator.expect(:call, nil, ['bin/rails generate model MyModel', verbose: false]) - generator.stub(:run_ruby_script, @mock_generator) do + assert_called_with(generator, :run_ruby_script, ['bin/rails generate model MyModel', verbose: false]) do action :generate, 'model', 'MyModel' end end def test_rake_should_run_rake_command_with_default_env - @mock_generator.expect(:call, nil, ["rake log:clear RAILS_ENV=development", verbose: false]) - generator.stub(:run, @mock_generator) do + assert_called_with(generator, :run, ["rake log:clear RAILS_ENV=development", verbose: false]) do with_rails_env nil do action :rake, 'log:clear' end @@ -201,15 +193,13 @@ class ActionsTest < Rails::Generators::TestCase end def test_rake_with_env_option_should_run_rake_command_in_env - @mock_generator.expect(:call, nil, ['rake log:clear RAILS_ENV=production', verbose: false]) - generator.stub(:run, @mock_generator) do + assert_called_with(generator, :run, ['rake log:clear RAILS_ENV=production', verbose: false]) do action :rake, 'log:clear', env: 'production' end end def test_rake_with_rails_env_variable_should_run_rake_command_in_env - @mock_generator.expect(:call, nil, ['rake log:clear RAILS_ENV=production', verbose: false]) - generator.stub(:run, @mock_generator) do + assert_called_with(generator, :run, ['rake log:clear RAILS_ENV=production', verbose: false]) do with_rails_env "production" do action :rake, 'log:clear' end @@ -217,8 +207,7 @@ class ActionsTest < Rails::Generators::TestCase end def test_env_option_should_win_over_rails_env_variable_when_running_rake - @mock_generator.expect(:call, nil, ['rake log:clear RAILS_ENV=production', verbose: false]) - generator.stub(:run, @mock_generator) do + assert_called_with(generator, :run, ['rake log:clear RAILS_ENV=production', verbose: false]) do with_rails_env "staging" do action :rake, 'log:clear', env: 'production' end @@ -226,8 +215,7 @@ class ActionsTest < Rails::Generators::TestCase end def test_rake_with_sudo_option_should_run_rake_command_with_sudo - @mock_generator.expect(:call, nil, ["sudo rake log:clear RAILS_ENV=development", verbose: false]) - generator.stub(:run, @mock_generator) do + assert_called_with(generator, :run, ["sudo rake log:clear RAILS_ENV=development", verbose: false]) do with_rails_env nil do action :rake, 'log:clear', sudo: true end @@ -235,8 +223,7 @@ class ActionsTest < Rails::Generators::TestCase end def test_capify_should_run_the_capify_command - @mock_generator.expect(:call, nil, ['capify .', verbose: false]) - generator.stub(:run, @mock_generator) do + assert_called_with(generator, :run, ['capify .', verbose: false]) do action :capify! end end @@ -274,8 +261,7 @@ F def test_readme run_generator - 2.times { @mock_generator.expect(:call, destination_root,[]) } - Rails::Generators::AppGenerator.stub(:source_root, @mock_generator) do + assert_called(Rails::Generators::AppGenerator, :source_root, times: 2, returns: destination_root) do assert_match "application up and running", action(:readme, "README.md") end end @@ -283,8 +269,7 @@ F def test_readme_with_quiet generator(default_arguments, quiet: true) run_generator - 2.times { @mock_generator.expect(:call, destination_root,[]) } - Rails::Generators::AppGenerator.stub(:source_root, @mock_generator) do + assert_called(Rails::Generators::AppGenerator, :source_root, times: 2, returns: destination_root) do assert_no_match "application up and running", action(:readme, "README.md") end end diff --git a/railties/test/generators/api_app_generator_test.rb b/railties/test/generators/api_app_generator_test.rb index 9978ad0da1..998da3ef84 100644 --- a/railties/test/generators/api_app_generator_test.rb +++ b/railties/test/generators/api_app_generator_test.rb @@ -38,6 +38,7 @@ class ApiAppGeneratorTest < Rails::Generators::TestCase assert_no_match(/gem 'jquery-rails'/, content) assert_no_match(/gem 'sass-rails'/, content) assert_no_match(/gem 'jbuilder'/, content) + assert_no_match(/gem 'web-console'/, content) assert_match(/gem 'active_model_serializers'/, content) end diff --git a/railties/test/generators/generators_test_helper.rb b/railties/test/generators/generators_test_helper.rb index 62ca0ecb4b..b19a5a7144 100644 --- a/railties/test/generators/generators_test_helper.rb +++ b/railties/test/generators/generators_test_helper.rb @@ -1,6 +1,7 @@ require 'abstract_unit' require 'active_support/core_ext/module/remove_method' require 'active_support/testing/stream' +require 'active_support/testing/method_call_assertions' require 'rails/generators' require 'rails/generators/test_case' @@ -25,6 +26,7 @@ require 'action_view' module GeneratorsTestHelper include ActiveSupport::Testing::Stream + include ActiveSupport::Testing::MethodCallAssertions def self.included(base) base.class_eval do diff --git a/railties/test/generators/named_base_test.rb b/railties/test/generators/named_base_test.rb index 1c32fc1bfd..291f5e06c3 100644 --- a/railties/test/generators/named_base_test.rb +++ b/railties/test/generators/named_base_test.rb @@ -1,6 +1,5 @@ require 'generators/generators_test_helper' require 'rails/generators/rails/scaffold_controller/scaffold_controller_generator' -require 'minitest/mock' class NamedBaseTest < Rails::Generators::TestCase include GeneratorsTestHelper diff --git a/railties/test/generators/plugin_generator_test.rb b/railties/test/generators/plugin_generator_test.rb index 73e68863f4..afccf9d885 100644 --- a/railties/test/generators/plugin_generator_test.rb +++ b/railties/test/generators/plugin_generator_test.rb @@ -313,6 +313,7 @@ class PluginGeneratorTest < Rails::Generators::TestCase assert_file "test/test_helper.rb" do |content| assert_match(/ActiveRecord::Migrator\.migrations_paths.+\.\.\/test\/dummy\/db\/migrate/, content) assert_match(/ActiveRecord::Migrator\.migrations_paths.+<<.+\.\.\/db\/migrate/, content) + assert_match(/ActionDispatch::IntegrationTest\.fixture_path = ActiveSupport::TestCase\.fixture_pat/, content) end end @@ -322,7 +323,7 @@ class PluginGeneratorTest < Rails::Generators::TestCase assert_file "hyphenated-name/app/assets/stylesheets/hyphenated/name" assert_file "hyphenated-name/app/assets/images/hyphenated/name" assert_file "hyphenated-name/config/routes.rb", /Hyphenated::Name::Engine.routes.draw do/ - assert_file "hyphenated-name/lib/hyphenated/name/version.rb", /module Hyphenated\n module Name\n VERSION = "0.0.1"\n end\nend/ + assert_file "hyphenated-name/lib/hyphenated/name/version.rb", /module Hyphenated\n module Name\n VERSION = '0.1.0'\n end\nend/ assert_file "hyphenated-name/lib/hyphenated/name/engine.rb", /module Hyphenated\n module Name\n class Engine < ::Rails::Engine\n isolate_namespace Hyphenated::Name\n end\n end\nend/ assert_file "hyphenated-name/lib/hyphenated/name.rb", /require "hyphenated\/name\/engine"/ assert_file "hyphenated-name/test/dummy/config/routes.rb", /mount Hyphenated::Name::Engine => "\/hyphenated-name"/ @@ -341,7 +342,7 @@ class PluginGeneratorTest < Rails::Generators::TestCase assert_file "my_hyphenated-name/app/assets/stylesheets/my_hyphenated/name" assert_file "my_hyphenated-name/app/assets/images/my_hyphenated/name" assert_file "my_hyphenated-name/config/routes.rb", /MyHyphenated::Name::Engine.routes.draw do/ - assert_file "my_hyphenated-name/lib/my_hyphenated/name/version.rb", /module MyHyphenated\n module Name\n VERSION = "0.0.1"\n end\nend/ + assert_file "my_hyphenated-name/lib/my_hyphenated/name/version.rb", /module MyHyphenated\n module Name\n VERSION = '0.1.0'\n end\nend/ assert_file "my_hyphenated-name/lib/my_hyphenated/name/engine.rb", /module MyHyphenated\n module Name\n class Engine < ::Rails::Engine\n isolate_namespace MyHyphenated::Name\n end\n end\nend/ assert_file "my_hyphenated-name/lib/my_hyphenated/name.rb", /require "my_hyphenated\/name\/engine"/ assert_file "my_hyphenated-name/test/dummy/config/routes.rb", /mount MyHyphenated::Name::Engine => "\/my_hyphenated-name"/ @@ -360,7 +361,7 @@ class PluginGeneratorTest < Rails::Generators::TestCase assert_file "deep-hyphenated-name/app/assets/stylesheets/deep/hyphenated/name" assert_file "deep-hyphenated-name/app/assets/images/deep/hyphenated/name" assert_file "deep-hyphenated-name/config/routes.rb", /Deep::Hyphenated::Name::Engine.routes.draw do/ - assert_file "deep-hyphenated-name/lib/deep/hyphenated/name/version.rb", /module Deep\n module Hyphenated\n module Name\n VERSION = "0.0.1"\n end\n end\nend/ + assert_file "deep-hyphenated-name/lib/deep/hyphenated/name/version.rb", /module Deep\n module Hyphenated\n module Name\n VERSION = '0.1.0'\n end\n end\nend/ assert_file "deep-hyphenated-name/lib/deep/hyphenated/name/engine.rb", /module Deep\n module Hyphenated\n module Name\n class Engine < ::Rails::Engine\n isolate_namespace Deep::Hyphenated::Name\n end\n end\n end\nend/ assert_file "deep-hyphenated-name/lib/deep/hyphenated/name.rb", /require "deep\/hyphenated\/name\/engine"/ assert_file "deep-hyphenated-name/test/dummy/config/routes.rb", /mount Deep::Hyphenated::Name::Engine => "\/deep-hyphenated-name"/ @@ -544,6 +545,60 @@ class PluginGeneratorTest < Rails::Generators::TestCase end end + def test_skipping_useless_folders_generation_for_api_engines + ['--full', '--mountable'].each do |option| + run_generator [destination_root, option, '--api'] + + assert_no_directory "app/assets" + assert_no_directory "app/helpers" + assert_no_directory "app/views" + + FileUtils.rm_rf destination_root + end + end + + def test_application_controller_parent_for_mountable_api_plugins + run_generator [destination_root, '--mountable', '--api'] + + assert_file "app/controllers/bukkits/application_controller.rb" do |content| + assert_match "ApplicationController < ActionController::API", content + end + end + + def test_dummy_api_application_for_api_plugins + run_generator [destination_root, '--api'] + + assert_file "test/dummy/config/application.rb" do |content| + assert_match "config.api_only = true", content + end + end + + + def test_api_generators_configuration_for_api_engines + run_generator [destination_root, '--full', '--api'] + + assert_file "lib/bukkits/engine.rb" do |content| + assert_match "config.generators.api_only = true", content + end + end + + def test_scaffold_generator_for_mountable_api_plugins + run_generator [destination_root, '--mountable', '--api'] + + capture(:stdout) do + `#{destination_root}/bin/rails g scaffold article` + end + + assert_file "app/models/bukkits/article.rb" + assert_file "app/controllers/bukkits/articles_controller.rb" do |content| + assert_match "only: [:show, :update, :destroy]", content + end + + assert_no_directory "app/assets" + assert_no_directory "app/helpers" + assert_no_directory "app/views" + end + protected def action(*args, &block) silence(:stdout){ generator.send(*args, &block) } diff --git a/railties/test/generators/scaffold_generator_test.rb b/railties/test/generators/scaffold_generator_test.rb index a853bfbe21..0c3808a9a0 100644 --- a/railties/test/generators/scaffold_generator_test.rb +++ b/railties/test/generators/scaffold_generator_test.rb @@ -505,4 +505,32 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase assert_match(/8 runs, 13 assertions, 0 failures, 0 errors/, `bin/rails test 2>&1`) end end + + def test_scaffold_tests_pass_by_default_inside_api_mountable_engine + Dir.chdir(destination_root) { `bundle exec rails plugin new bukkits --mountable --api` } + + engine_path = File.join(destination_root, "bukkits") + + Dir.chdir(engine_path) do + quietly do + `bin/rails g scaffold User name:string age:integer; + bundle exec rake db:migrate` + end + assert_match(/6 runs, 8 assertions, 0 failures, 0 errors/, `bin/rails test 2>&1`) + end + end + + def test_scaffold_tests_pass_by_default_inside_api_full_engine + Dir.chdir(destination_root) { `bundle exec rails plugin new bukkits --full --api` } + + engine_path = File.join(destination_root, "bukkits") + + Dir.chdir(engine_path) do + quietly do + `bin/rails g scaffold User name:string age:integer; + bundle exec rake db:migrate` + end + assert_match(/6 runs, 8 assertions, 0 failures, 0 errors/, `bin/rails test 2>&1`) + end + end end diff --git a/railties/test/generators_test.rb b/railties/test/generators_test.rb index 31a575749a..291415858c 100644 --- a/railties/test/generators_test.rb +++ b/railties/test/generators_test.rb @@ -1,7 +1,6 @@ require 'generators/generators_test_helper' require 'rails/generators/rails/model/model_generator' require 'rails/generators/test_unit/model/model_generator' -require 'minitest/mock' class GeneratorsTest < Rails::Generators::TestCase include GeneratorsTestHelper @@ -9,18 +8,15 @@ class GeneratorsTest < Rails::Generators::TestCase def setup @path = File.expand_path("lib", Rails.root) $LOAD_PATH.unshift(@path) - @mock_generator = MiniTest::Mock.new end def teardown $LOAD_PATH.delete(@path) - @mock_generator.verify end def test_simple_invoke assert File.exist?(File.join(@path, 'generators', 'model_generator.rb')) - @mock_generator.expect(:call, nil, [["Account"],{}]) - TestUnit::Generators::ModelGenerator.stub(:start, @mock_generator) do + assert_called_with(TestUnit::Generators::ModelGenerator, :start, [["Account"], {}]) do Rails::Generators.invoke("test_unit:model", ["Account"]) end end @@ -51,23 +47,20 @@ class GeneratorsTest < Rails::Generators::TestCase def test_should_give_higher_preference_to_rails_generators assert File.exist?(File.join(@path, 'generators', 'model_generator.rb')) - @mock_generator.expect(:call, nil, [["Account"],{}]) - Rails::Generators::ModelGenerator.stub(:start, @mock_generator) do + assert_called_with(Rails::Generators::ModelGenerator, :start, [["Account"], {}]) do warnings = capture(:stderr){ Rails::Generators.invoke :model, ["Account"] } assert warnings.empty? end end def test_invoke_with_default_values - @mock_generator.expect(:call, nil, [["Account"],{}]) - Rails::Generators::ModelGenerator.stub(:start, @mock_generator) do + assert_called_with(Rails::Generators::ModelGenerator, :start, [["Account"], {}]) do Rails::Generators.invoke :model, ["Account"] end end def test_invoke_with_config_values - @mock_generator.expect(:call, nil, [["Account"],{behavior: :skip}]) - Rails::Generators::ModelGenerator.stub(:start, @mock_generator) do + assert_called_with(Rails::Generators::ModelGenerator, :start, [["Account"], behavior: :skip]) do Rails::Generators.invoke :model, ["Account"], behavior: :skip end end @@ -115,8 +108,7 @@ class GeneratorsTest < Rails::Generators::TestCase def test_invoke_with_nested_namespaces model_generator = Minitest::Mock.new model_generator.expect(:start, nil, [["Account"], {}]) - @mock_generator.expect(:call, model_generator, ['namespace', 'my:awesome']) - Rails::Generators.stub(:find_by_namespace, @mock_generator) do + assert_called_with(Rails::Generators, :find_by_namespace, ['namespace', 'my:awesome'], returns: model_generator) do Rails::Generators.invoke 'my:awesome:namespace', ["Account"] end model_generator.verify @@ -185,8 +177,7 @@ class GeneratorsTest < Rails::Generators::TestCase def test_fallbacks_for_generators_on_invoke Rails::Generators.fallbacks[:shoulda] = :test_unit - @mock_generator.expect(:call, nil, [["Account"],{}]) - TestUnit::Generators::ModelGenerator.stub(:start, @mock_generator) do + assert_called_with(TestUnit::Generators::ModelGenerator, :start, [["Account"], {}]) do Rails::Generators.invoke "shoulda:model", ["Account"] end ensure @@ -196,8 +187,7 @@ class GeneratorsTest < Rails::Generators::TestCase def test_nested_fallbacks_for_generators Rails::Generators.fallbacks[:shoulda] = :test_unit Rails::Generators.fallbacks[:super_shoulda] = :shoulda - @mock_generator.expect(:call, nil, [["Account"],{}]) - TestUnit::Generators::ModelGenerator.stub(:start, @mock_generator) do + assert_called_with(TestUnit::Generators::ModelGenerator, :start, [["Account"], {}]) do Rails::Generators.invoke "super_shoulda:model", ["Account"] end ensure diff --git a/railties/test/path_generation_test.rb b/railties/test/path_generation_test.rb index 27e64b97b7..a16adc72a6 100644 --- a/railties/test/path_generation_test.rb +++ b/railties/test/path_generation_test.rb @@ -11,26 +11,26 @@ class PathGenerationTest < ActiveSupport::TestCase super() end - class Dispatcher < ActionDispatch::Routing::RouteSet::Dispatcher - def initialize(defaults, set, block) - super(defaults) + class Request < DelegateClass(ActionDispatch::Request) + def initialize(target, url_helpers, block) + super(target) + @url_helpers = url_helpers @block = block - @set = set end - def controller_reference(controller_param) + def controller_class + url_helpers = @url_helpers block = @block - set = @set Class.new(ActionController::Base) { - include set.url_helpers + include url_helpers define_method(:process) { |name| block.call(self) } def to_a; [200, {}, []]; end } end end - def dispatcher defaults - TestSet::Dispatcher.new defaults, self, @block + def make_request(env) + Request.new super, self.url_helpers, @block end end diff --git a/railties/test/paths_test.rb b/railties/test/paths_test.rb index 12630e4d01..96b54c7264 100644 --- a/railties/test/paths_test.rb +++ b/railties/test/paths_test.rb @@ -62,6 +62,13 @@ class PathsTest < ActiveSupport::TestCase assert_equal ["/foo/bar/baz"], @root["app/models"].to_a end + test "absolute current path" do + @root.add "config" + @root.add "config/locales" + + assert_equal "/foo/bar/config/locales", @root["config/locales"].absolute_current + end + test "adding multiple physical paths as an array" do @root.add "app", with: ["/app", "/app2"] assert_equal ["/app", "/app2"], @root["app"].to_a @@ -215,6 +222,12 @@ class PathsTest < ActiveSupport::TestCase assert_equal "*.rb", @root["app"].glob end + test "it should be possible to get extensions by glob" do + @root["app"] = "/app" + @root["app"].glob = "*.{rb,yml}" + assert_equal ["rb", "yml"], @root["app"].extensions + end + test "it should be possible to override a path's default glob without assignment" do @root.add "app", with: "/app", glob: "*.rb" assert_equal "*.rb", @root["app"].glob |