aboutsummaryrefslogtreecommitdiffstats
path: root/railties
diff options
context:
space:
mode:
Diffstat (limited to 'railties')
-rw-r--r--railties/CHANGELOG.md7
-rw-r--r--railties/guides/source/caching_with_rails.textile8
-rw-r--r--railties/guides/source/configuring.textile2
-rw-r--r--railties/lib/rails/application.rb40
-rw-r--r--railties/lib/rails/application/configuration.rb49
-rw-r--r--railties/lib/rails/application/finisher.rb14
-rw-r--r--railties/lib/rails/application/routes_reloader.rb12
-rw-r--r--railties/lib/rails/engine.rb2
-rw-r--r--railties/lib/rails/generators/app_base.rb2
-rw-r--r--railties/lib/rails/railtie/configuration.rb12
-rw-r--r--railties/test/application/console_test.rb3
-rw-r--r--railties/test/application/loading_test.rb1
-rw-r--r--railties/test/application/middleware/cache_test.rb4
-rw-r--r--railties/test/generators/app_generator_test.rb10
14 files changed, 116 insertions, 50 deletions
diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md
index 2841996b56..a88f443517 100644
--- a/railties/CHANGELOG.md
+++ b/railties/CHANGELOG.md
@@ -1,9 +1,8 @@
## Rails 3.2.0 (unreleased) ##
-* New applications get a flag
- `config.active_record.auto_explain_threshold_in_seconds` in the environments
- configuration files. With a value of 0.5 in development.rb, and commented
- out in production.rb. No mention in test.rb. *fxn*
+* Speed up development by only reloading classes if dependencies files changed. This can be turned off by setting `config.reload_classes_only_on_change` to false. *José Valim*
+
+* New applications get a flag `config.active_record.auto_explain_threshold_in_seconds` in the environments configuration files. With a value of 0.5 in development.rb, and commented out in production.rb. No mention in test.rb. *fxn*
* Add DebugExceptions middleware which contains features extracted from ShowExceptions middleware *José Valim*
diff --git a/railties/guides/source/caching_with_rails.textile b/railties/guides/source/caching_with_rails.textile
index 0ef6f51190..ec9bfd4d40 100644
--- a/railties/guides/source/caching_with_rails.textile
+++ b/railties/guides/source/caching_with_rails.textile
@@ -332,6 +332,14 @@ caches_action :index, :expires_in => 60.seconds, :unless_exist => true
For more information about Ehcache, see "http://ehcache.org/":http://ehcache.org/ .
For more information about Ehcache for JRuby and Rails, see "http://ehcache.org/documentation/jruby.html":http://ehcache.org/documentation/jruby.html
+h4. ActiveSupport::Cache::NullStore
+
+This cache store implementation is meant to be used only in development or test environments and it never stores anything. This can be very useful in development when you have code that interacts directly with +Rails.cache+, but caching may interfere with being able to see the results of code changes. With this cache store, all +fetch+ and +read+ operations will result in a miss.
+
+<ruby>
+ActionController::Base.cache_store = :null
+</ruby>
+
h4. Custom Cache Stores
You can create your own custom cache store by simply extending +ActiveSupport::Cache::Store+ and implementing the appropriate methods. In this way, you can swap in any number of caching technologies into your Rails application.
diff --git a/railties/guides/source/configuring.textile b/railties/guides/source/configuring.textile
index 8e65dbccbb..8cf88cf71f 100644
--- a/railties/guides/source/configuring.textile
+++ b/railties/guides/source/configuring.textile
@@ -98,6 +98,8 @@ NOTE. The +config.asset_path+ configuration is ignored if the asset pipeline is
* +config.preload_frameworks+ enables or disables preloading all frameworks at startup. Enabled by +config.threadsafe!+. Defaults to +nil+, so is disabled.
+* +config.reload_classes_only_on_change+ enables or disables reloading of classes only when tracked files change. By default tracks everything on autoload paths and is set to true.
+
* +config.reload_plugins+ enables or disables plugin reloading. Defaults to false.
* +config.secret_token+ used for specifying a key which allows sessions for the application to be verified against a known secure key to prevent tampering. Applications get +config.secret_token+ initialized to a random key in +config/initializers/secret_token.rb+.
diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb
index acbfd7078b..0b8eac8a8b 100644
--- a/railties/lib/rails/application.rb
+++ b/railties/lib/rails/application.rb
@@ -71,12 +71,14 @@ module Rails
attr_accessor :assets, :sandbox
alias_method :sandbox?, :sandbox
+ attr_reader :reloaders
delegate :default_url_options, :default_url_options=, :to => :routes
def initialize
super
@initialized = false
+ @reloaders = []
end
# This method is called just after an application inherits from Rails::Application,
@@ -119,6 +121,7 @@ module Rails
reloader = routes_reloader
hook = lambda { reloader.execute_if_updated }
hook.call
+ self.reloaders << reloader
ActionDispatch::Reloader.to_prepare(&hook)
end
@@ -126,10 +129,35 @@ module Rails
# A plugin may override this if they desire to provide a more exquisite app reloading.
# :api: plugin
def set_dependencies_hook
- ActionDispatch::Reloader.to_cleanup do
+ callback = lambda do
ActiveSupport::DescendantsTracker.clear
ActiveSupport::Dependencies.clear
end
+
+ if config.reload_classes_only_on_change
+ reloader = ActiveSupport::FileUpdateChecker.new(watchable_args, true, &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, &callback)
+ else
+ ActionDispatch::Reloader.to_cleanup(&callback)
+ end
+ end
+
+ # Returns an array of file paths appended with a hash of directories-extensions
+ # suitable for ActiveSupport::FileUpdateChecker API.
+ def watchable_args
+ files = []
+ files.concat config.watchable_files
+
+ dirs = {}
+ dirs.merge! config.watchable_dirs
+ ActiveSupport::Dependencies.autoload_paths.each do |path|
+ dirs[path.to_s] = [:rb]
+ end
+
+ files << dirs
end
# Initialize the application passing the given group. By default, the
@@ -223,6 +251,10 @@ module Rails
alias :build_middleware_stack :app
+ def reload_dependencies?
+ config.reload_classes_only_on_change != true || reloaders.map(&:updated?).any?
+ end
+
def default_middleware_stack
ActionDispatch::MiddlewareStack.new.tap do |middleware|
if rack_cache = config.action_controller.perform_caching && config.action_dispatch.rack_cache
@@ -252,7 +284,11 @@ module Rails
middleware.use ::Rack::Sendfile, config.action_dispatch.x_sendfile_header
end
- middleware.use ::ActionDispatch::Reloader unless config.cache_classes
+ unless config.cache_classes
+ app = self
+ middleware.use ::ActionDispatch::Reloader, lambda { app.reload_dependencies? }
+ end
+
middleware.use ::ActionDispatch::Callbacks
middleware.use ::ActionDispatch::Cookies
diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb
index 4b2afe3a28..39d66ecc31 100644
--- a/railties/lib/rails/application/configuration.rb
+++ b/railties/lib/rails/application/configuration.rb
@@ -7,11 +7,11 @@ module Rails
class Configuration < ::Rails::Engine::Configuration
attr_accessor :allow_concurrency, :asset_host, :asset_path, :assets,
:cache_classes, :cache_store, :consider_all_requests_local,
- :dependency_loading, :filter_parameters,
- :force_ssl, :helpers_paths, :logger, :log_tags, :preload_frameworks,
- :relative_url_root, :reload_plugins, :secret_token, :serve_static_assets,
- :ssl_options, :static_cache_control, :session_options,
- :time_zone, :whiny_nils, :railties_order, :all_initializers
+ :dependency_loading, :filter_parameters, :force_ssl, :helpers_paths,
+ :initializers_paths, :logger, :log_tags, :preload_frameworks,
+ :railties_order, :relative_url_root, :reload_plugins, :secret_token,
+ :serve_static_assets, :ssl_options, :static_cache_control, :session_options,
+ :time_zone, :reload_classes_only_on_change, :whiny_nils
attr_writer :log_level
attr_reader :encoding
@@ -19,25 +19,26 @@ module Rails
def initialize(*)
super
self.encoding = "utf-8"
- @allow_concurrency = false
- @consider_all_requests_local = false
- @filter_parameters = []
- @helpers_paths = []
- @dependency_loading = true
- @serve_static_assets = true
- @static_cache_control = nil
- @force_ssl = false
- @ssl_options = {}
- @session_store = :cookie_store
- @session_options = {}
- @time_zone = "UTC"
- @log_level = nil
- @middleware = app_middleware
- @generators = app_generators
- @cache_store = [ :file_store, "#{root}/tmp/cache/" ]
- @railties_order = [:all]
- @all_initializers = []
- @relative_url_root = ENV["RAILS_RELATIVE_URL_ROOT"]
+ @allow_concurrency = false
+ @consider_all_requests_local = false
+ @filter_parameters = []
+ @helpers_paths = []
+ @dependency_loading = true
+ @serve_static_assets = true
+ @static_cache_control = nil
+ @force_ssl = false
+ @ssl_options = {}
+ @session_store = :cookie_store
+ @session_options = {}
+ @time_zone = "UTC"
+ @log_level = nil
+ @middleware = app_middleware
+ @generators = app_generators
+ @cache_store = [ :file_store, "#{root}/tmp/cache/" ]
+ @railties_order = [:all]
+ @initializers_paths = []
+ @relative_url_root = ENV["RAILS_RELATIVE_URL_ROOT"]
+ @reload_classes_only_on_change = true
@assets = ActiveSupport::OrderedOptions.new
@assets.enabled = false
diff --git a/railties/lib/rails/application/finisher.rb b/railties/lib/rails/application/finisher.rb
index 17e7aa0f28..e000f6ef3a 100644
--- a/railties/lib/rails/application/finisher.rb
+++ b/railties/lib/rails/application/finisher.rb
@@ -5,7 +5,7 @@ module Rails
$rails_rake_task = nil
initializer :load_config_initializers do
- config.all_initializers.each { |init| load(init) }
+ config.initializers_paths.each { |init| load(init) }
end
initializer :add_generator_templates do
@@ -65,17 +65,17 @@ module Rails
end
# Set app reload just after the finisher hook to ensure
- # paths added in the hook are still loaded.
- initializer :set_dependencies_hook, :group => :all do |app|
- app.set_dependencies_hook
- end
-
- # Set app reload just after the finisher hook to ensure
# routes added in the hook are still loaded.
initializer :set_routes_reloader_hook do |app|
app.set_routes_reloader_hook
end
+ # Set app reload just after the finisher hook to ensure
+ # paths added in the hook are still loaded.
+ initializer :set_dependencies_hook, :group => :all do |app|
+ app.set_dependencies_hook
+ end
+
# Disable dependency loading during request cycle
initializer :disable_dependency_loading do
if config.cache_classes && !config.dependency_loading
diff --git a/railties/lib/rails/application/routes_reloader.rb b/railties/lib/rails/application/routes_reloader.rb
index c1f435a3ee..460b84dfd9 100644
--- a/railties/lib/rails/application/routes_reloader.rb
+++ b/railties/lib/rails/application/routes_reloader.rb
@@ -1,21 +1,17 @@
+require "active_support/core_ext/module/delegation"
+
module Rails
class Application
class RoutesReloader
attr_reader :route_sets
+ delegate :paths, :execute_if_updated, :updated?, :to => :@updater
+
def initialize(updater=ActiveSupport::FileUpdateChecker)
@updater = updater.new([]) { reload! }
@route_sets = []
end
- def paths
- @updater.paths
- end
-
- def execute_if_updated
- @updater.execute_if_updated
- end
-
def reload!
clear!
load_paths
diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb
index 8ebe1f48a5..86efc7332c 100644
--- a/railties/lib/rails/engine.rb
+++ b/railties/lib/rails/engine.rb
@@ -584,7 +584,7 @@ module Rails
end
initializer :append_config_initializers do |app|
- app.config.all_initializers.concat config.paths["config/initializers"].existent.sort
+ app.config.initializers_paths.concat config.paths["config/initializers"].existent.sort
end
initializer :engines_blank_point do
diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb
index e3d22e81fb..0bd39cb2cd 100644
--- a/railties/lib/rails/generators/app_base.rb
+++ b/railties/lib/rails/generators/app_base.rb
@@ -194,7 +194,7 @@ module Rails
def assets_gemfile_entry
return if options[:skip_sprockets]
- <<-GEMFILE.strip_heredoc
+ <<-GEMFILE.strip_heredoc.gsub(/^[ \t]*$/, '')
# Gems used only for assets and not required
# in production environments by default.
group :assets do
diff --git a/railties/lib/rails/railtie/configuration.rb b/railties/lib/rails/railtie/configuration.rb
index f888684117..cf9e4ad500 100644
--- a/railties/lib/rails/railtie/configuration.rb
+++ b/railties/lib/rails/railtie/configuration.rb
@@ -7,6 +7,18 @@ module Rails
@@options ||= {}
end
+ # Add files that should be watched for change.
+ def watchable_files
+ @@watchable_files ||= []
+ end
+
+ # Add directories that should be watched for change.
+ # The key of the hashes should be directories and the values should
+ # be an array of extensions to match in each directory.
+ def watchable_dirs
+ @@watchable_dirs ||= {}
+ end
+
# This allows you to modify the application's middlewares from Engines.
#
# All operations you run on the app_middleware will be replayed on the
diff --git a/railties/test/application/console_test.rb b/railties/test/application/console_test.rb
index 2073c780bf..6f9d8d57b1 100644
--- a/railties/test/application/console_test.rb
+++ b/railties/test/application/console_test.rb
@@ -61,7 +61,8 @@ class ConsoleTest < Test::Unit::TestCase
load_environment
assert User.new.respond_to?(:name)
- assert !User.new.respond_to?(:age)
+
+ sleep(1)
app_file "app/models/user.rb", <<-MODEL
class User
diff --git a/railties/test/application/loading_test.rb b/railties/test/application/loading_test.rb
index 47c6fd5c6e..c4908915dc 100644
--- a/railties/test/application/loading_test.rb
+++ b/railties/test/application/loading_test.rb
@@ -66,6 +66,7 @@ class LoadingTest < Test::Unit::TestCase
def test_descendants_are_cleaned_on_each_request_without_cache_classes
add_to_config <<-RUBY
config.cache_classes = false
+ config.reload_classes_only_on_change = false
RUBY
app_file "app/models/post.rb", <<-MODEL
diff --git a/railties/test/application/middleware/cache_test.rb b/railties/test/application/middleware/cache_test.rb
index 050a2161ae..790c5b2d53 100644
--- a/railties/test/application/middleware/cache_test.rb
+++ b/railties/test/application/middleware/cache_test.rb
@@ -54,9 +54,9 @@ module ApplicationTests
def test_cache_keeps_if_modified_since
simple_controller
expected = "Wed, 30 May 1984 19:43:31 GMT"
-
+
get "/expires/keeps_if_modified_since", {}, "HTTP_IF_MODIFIED_SINCE" => expected
-
+
assert_equal 200, last_response.status
assert_equal expected, last_response.body, "cache should have kept If-Modified-Since"
end
diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb
index ef9f2b22a7..30fbe74e83 100644
--- a/railties/test/generators/app_generator_test.rb
+++ b/railties/test/generators/app_generator_test.rb
@@ -124,6 +124,16 @@ class AppGeneratorTest < Rails::Generators::TestCase
assert_file "hats/config/environment.rb", /Hats::Application\.initialize!/
end
+ def test_gemfile_has_no_whitespace_errors
+ run_generator
+ absolute = File.expand_path("Gemfile", destination_root)
+ File.open(absolute, 'r') do |f|
+ f.each_line do |line|
+ assert_no_match /^[ \t]+$/, line
+ end
+ end
+ end
+
def test_config_database_is_added_by_default
run_generator
assert_file "config/database.yml", /sqlite3/