diff options
author | Jeremy Kemper <jeremy@bitsweat.net> | 2008-04-20 15:30:41 -0700 |
---|---|---|
committer | Jeremy Kemper <jeremy@bitsweat.net> | 2008-04-20 15:30:41 -0700 |
commit | 3b93ca221d3a1b777bd880c18f52010cbd56c18c (patch) | |
tree | 7b49713994125de123775102eac2655d7b29b231 /actionpack/lib | |
parent | daab53d8c0bca1114c1485d0dcc52858a264ab9e (diff) | |
parent | 46ab7422d9ebac0d529f71a3a7c2feaf0b9d5dbd (diff) | |
download | rails-3b93ca221d3a1b777bd880c18f52010cbd56c18c.tar.gz rails-3b93ca221d3a1b777bd880c18f52010cbd56c18c.tar.bz2 rails-3b93ca221d3a1b777bd880c18f52010cbd56c18c.zip |
Merge commit 'rails/master'
Diffstat (limited to 'actionpack/lib')
-rwxr-xr-x | actionpack/lib/action_controller/base.rb | 20 | ||||
-rw-r--r-- | actionpack/lib/action_controller/caching/pages.rb | 16 | ||||
-rw-r--r-- | actionpack/lib/action_controller/dispatcher.rb | 77 | ||||
-rw-r--r-- | actionpack/lib/action_controller/filters.rb | 6 | ||||
-rw-r--r-- | actionpack/lib/action_controller/layout.rb | 4 | ||||
-rw-r--r-- | actionpack/lib/action_controller/rescue.rb | 4 | ||||
-rw-r--r-- | actionpack/lib/action_view.rb | 7 | ||||
-rw-r--r-- | actionpack/lib/action_view/base.rb | 15 | ||||
-rw-r--r-- | actionpack/lib/action_view/helpers/asset_tag_helper.rb | 8 | ||||
-rw-r--r-- | actionpack/lib/action_view/inline_template.rb | 20 | ||||
-rw-r--r-- | actionpack/lib/action_view/template.rb | 38 | ||||
-rw-r--r-- | actionpack/lib/action_view/test_case.rb | 64 |
12 files changed, 177 insertions, 102 deletions
diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index 63ad4d042a..c0f3122fbf 100755 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -16,9 +16,6 @@ module ActionController #:nodoc: class SessionRestoreError < ActionControllerError #:nodoc: end - class MissingTemplate < ActionControllerError #:nodoc: - end - class RenderError < ActionControllerError #:nodoc: end @@ -330,9 +327,6 @@ module ActionController #:nodoc: # Can be set to nil for no logging. Compatible with both Ruby's own Logger and Log4r loggers. cattr_accessor :logger - # Turn on +ignore_missing_templates+ if you want to unit test actions without making the associated templates. - cattr_accessor :ignore_missing_templates - # Controls the resource action separator @@resource_action_separator = "/" cattr_accessor :resource_action_separator @@ -870,7 +864,7 @@ module ActionController #:nodoc: elsif inline = options[:inline] add_variables_to_assigns - tmpl = ActionView::Template.new(@template, options[:inline], false, options[:locals], true, options[:type]) + tmpl = ActionView::InlineTemplate.new(@template, options[:inline], options[:locals], options[:type]) render_for_text(@template.render_template(tmpl), options[:status]) elsif action_name = options[:action] @@ -1105,7 +1099,6 @@ module ActionController #:nodoc: private def render_for_file(template_path, status = nil, use_full_path = false, locals = {}) #:nodoc: add_variables_to_assigns - assert_existence_of_template_file(template_path) if use_full_path logger.info("Rendering #{template_path}" + (status ? " (#{status})" : '')) if logger render_for_text(@template.render_file(template_path, use_full_path, locals), status) end @@ -1223,7 +1216,7 @@ module ActionController #:nodoc: end def add_class_variables_to_assigns - %w(view_paths logger ignore_missing_templates).each do |cvar| + %w(view_paths logger).each do |cvar| @assigns[cvar] = self.send(cvar) end end @@ -1267,15 +1260,6 @@ module ActionController #:nodoc: @@exempt_from_layout.any? { |ext| name_with_extension =~ ext } end - def assert_existence_of_template_file(template_name) - unless template_exists?(template_name) || ignore_missing_templates - full_template_path = template_name.include?('.') ? template_name : "#{template_name}.#{@template.template_format}.erb" - display_paths = view_paths.join(':') - template_type = (template_name =~ /layouts/i) ? 'layout' : 'template' - raise(MissingTemplate, "Missing #{template_type} #{full_template_path} in view path #{display_paths}") - end - end - def default_template_name(action_name = self.action_name) if action_name action_name = action_name.to_s diff --git a/actionpack/lib/action_controller/caching/pages.rb b/actionpack/lib/action_controller/caching/pages.rb index 4307f39583..7aa6ce154b 100644 --- a/actionpack/lib/action_controller/caching/pages.rb +++ b/actionpack/lib/action_controller/caching/pages.rb @@ -36,7 +36,7 @@ module ActionController #:nodoc: # == Setting the cache directory # # The cache directory should be the document root for the web server and is set using Base.page_cache_directory = "/document/root". - # For Rails, this directory has already been set to RAILS_ROOT + "/public". + # For Rails, this directory has already been set to Rails.public_path (which is usually set to RAILS_ROOT + "/public"). # # == Setting the cache extension # @@ -46,7 +46,7 @@ module ActionController #:nodoc: def self.included(base) #:nodoc: base.extend(ClassMethods) base.class_eval do - @@page_cache_directory = defined?(RAILS_ROOT) ? "#{RAILS_ROOT}/public" : "" + @@page_cache_directory = defined?(Rails.public_path) ? Rails.public_path : "" cattr_accessor :page_cache_directory @@page_cache_extension = '.html' @@ -78,10 +78,18 @@ module ActionController #:nodoc: # Caches the +actions+ using the page-caching approach that'll store the cache in a path within the page_cache_directory that # matches the triggering url. + # + # Usage: + # + # # cache the index action + # caches_page :index + # + # # cache the index action except for JSON requests + # caches_page :index, :if => Proc.new { |c| !c.request.format.json? } def caches_page(*actions) return unless perform_caching - actions = actions.map(&:to_s) - after_filter { |c| c.cache_page if actions.include?(c.action_name) } + options = actions.extract_options! + after_filter({:only => actions}.merge(options)) { |c| c.cache_page } end private diff --git a/actionpack/lib/action_controller/dispatcher.rb b/actionpack/lib/action_controller/dispatcher.rb index 92576bdb2b..6e1e7a261f 100644 --- a/actionpack/lib/action_controller/dispatcher.rb +++ b/actionpack/lib/action_controller/dispatcher.rb @@ -5,6 +5,30 @@ module ActionController @@guard = Mutex.new class << self + def define_dispatcher_callbacks(cache_classes) + unless cache_classes + # Development mode callbacks + before_dispatch :reload_application + after_dispatch :cleanup_application + end + + # Common callbacks + to_prepare :load_application_controller do + begin + require_dependency 'application' unless defined?(::ApplicationController) + rescue LoadError => error + raise unless error.message =~ /application\.rb/ + end + end + + if defined?(ActiveRecord) + before_dispatch { ActiveRecord::Base.verify_active_connections! } + to_prepare(:activerecord_instantiate_observers) { ActiveRecord::Base.instantiate_observers } + end + + after_dispatch :flush_logger if defined?(RAILS_DEFAULT_LOGGER) && RAILS_DEFAULT_LOGGER.respond_to?(:flush) + end + # Backward-compatible class method takes CGI-specific args. Deprecated # in favor of Dispatcher.new(output, request, response).dispatch. def dispatch(cgi = nil, session_options = CgiRequest::DEFAULT_SESSION_OPTIONS, output = $stdout) @@ -22,7 +46,7 @@ module ActionController def to_prepare(identifier = nil, &block) @prepare_dispatch_callbacks ||= ActiveSupport::Callbacks::CallbackChain.new callback = ActiveSupport::Callbacks::Callback.new(:prepare_dispatch, block, :identifier => identifier) - @prepare_dispatch_callbacks.replace_or_append_callback(callback) + @prepare_dispatch_callbacks | callback end # If the block raises, send status code as a last-ditch response. @@ -67,25 +91,11 @@ module ActionController end cattr_accessor :error_file_path - self.error_file_path = "#{::RAILS_ROOT}/public" if defined? ::RAILS_ROOT - - cattr_accessor :unprepared - self.unprepared = true + self.error_file_path = Rails.public_path if defined?(Rails.public_path) include ActiveSupport::Callbacks define_callbacks :prepare_dispatch, :before_dispatch, :after_dispatch - before_dispatch :reload_application - before_dispatch :prepare_application - after_dispatch :flush_logger - after_dispatch :cleanup_application - - if defined? ActiveRecord - to_prepare :activerecord_instantiate_observers do - ActiveRecord::Base.instantiate_observers - end - end - def initialize(output, request = nil, response = nil) @output, @request, @response = output, request, response end @@ -114,40 +124,23 @@ module ActionController end def reload_application - if Dependencies.load? - Routing::Routes.reload - self.unprepared = true - end - end + # Run prepare callbacks before every request in development mode + run_callbacks :prepare_dispatch - def prepare_application(force = false) - begin - require_dependency 'application' unless defined?(::ApplicationController) - rescue LoadError => error - raise unless error.message =~ /application\.rb/ - end - - ActiveRecord::Base.verify_active_connections! if defined?(ActiveRecord) - - if unprepared || force - run_callbacks :prepare_dispatch - ActionView::TemplateFinder.reload! unless ActionView::Base.cache_template_loading - self.unprepared = false - end + Routing::Routes.reload + ActionView::TemplateFinder.reload! unless ActionView::Base.cache_template_loading end # Cleanup the application by clearing out loaded classes so they can # be reloaded on the next request without restarting the server. - def cleanup_application(force = false) - if Dependencies.load? || force - ActiveRecord::Base.reset_subclasses if defined?(ActiveRecord) - Dependencies.clear - ActiveRecord::Base.clear_reloadable_connections! if defined?(ActiveRecord) - end + def cleanup_application + ActiveRecord::Base.reset_subclasses if defined?(ActiveRecord) + Dependencies.clear + ActiveRecord::Base.clear_reloadable_connections! if defined?(ActiveRecord) end def flush_logger - RAILS_DEFAULT_LOGGER.flush if defined?(RAILS_DEFAULT_LOGGER) && RAILS_DEFAULT_LOGGER.respond_to?(:flush) + RAILS_DEFAULT_LOGGER.flush end protected diff --git a/actionpack/lib/action_controller/filters.rb b/actionpack/lib/action_controller/filters.rb index 73721cd1ec..8c97787741 100644 --- a/actionpack/lib/action_controller/filters.rb +++ b/actionpack/lib/action_controller/filters.rb @@ -265,7 +265,7 @@ module ActionController #:nodoc: def skip_filter_in_chain(*filters, &test) filters, conditions = extract_options(filters) filters.each do |filter| - if callback = find_callback(filter) then delete(callback) end + if callback = find(filter) then delete(callback) end end if conditions.empty? update_filter_in_chain(filters, :skip => conditions, &test) end @@ -302,7 +302,7 @@ module ActionController #:nodoc: def find_or_create_filter(filter, filter_type, options = {}) update_filter_in_chain([filter], options) - if found_filter = find_callback(filter) { |f| f.type == filter_type } + if found_filter = find(filter) { |f| f.type == filter_type } found_filter else filter_kind = case @@ -326,7 +326,7 @@ module ActionController #:nodoc: end def update_filter_in_chain(filters, options, &test) - filters.map! { |f| block_given? ? find_callback(f, &test) : find_callback(f) } + filters.map! { |f| block_given? ? find(f, &test) : find(f) } filters.compact! map! do |filter| diff --git a/actionpack/lib/action_controller/layout.rb b/actionpack/lib/action_controller/layout.rb index 5484add3b5..b5b59f2d7c 100644 --- a/actionpack/lib/action_controller/layout.rb +++ b/actionpack/lib/action_controller/layout.rb @@ -244,9 +244,7 @@ module ActionController #:nodoc: def render_with_a_layout(options = nil, extra_options = {}, &block) #:nodoc: template_with_options = options.is_a?(Hash) - if apply_layout?(template_with_options, options) && (layout = pick_layout(template_with_options, options)) - assert_existence_of_template_file(layout) - + if (layout = pick_layout(template_with_options, options)) && apply_layout?(template_with_options, options) options = options.merge :layout => false if template_with_options logger.info("Rendering template within #{layout}") if logger diff --git a/actionpack/lib/action_controller/rescue.rb b/actionpack/lib/action_controller/rescue.rb index b91115a93c..d4d561bdb7 100644 --- a/actionpack/lib/action_controller/rescue.rb +++ b/actionpack/lib/action_controller/rescue.rb @@ -26,7 +26,7 @@ module ActionController #:nodoc: DEFAULT_RESCUE_TEMPLATE = 'diagnostics' DEFAULT_RESCUE_TEMPLATES = { - 'ActionController::MissingTemplate' => 'missing_template', + 'ActionView::MissingTemplate' => 'missing_template', 'ActionController::RoutingError' => 'routing_error', 'ActionController::UnknownAction' => 'unknown_action', 'ActionView::TemplateError' => 'template_error' @@ -153,7 +153,7 @@ module ActionController #:nodoc: # If the file doesn't exist, the body of the response will be left empty. def render_optional_error_file(status_code) status = interpret_status(status_code) - path = "#{RAILS_ROOT}/public/#{status[0,3]}.html" + path = "#{Rails.public_path}/#{status[0,3]}.html" if File.exist?(path) render :file => path, :status => status else diff --git a/actionpack/lib/action_view.rb b/actionpack/lib/action_view.rb index e20812d308..609334d52d 100644 --- a/actionpack/lib/action_view.rb +++ b/actionpack/lib/action_view.rb @@ -30,6 +30,7 @@ require 'action_view/template_handlers/rjs' require 'action_view/template_finder' require 'action_view/template' require 'action_view/partial_template' +require 'action_view/inline_template' require 'action_view/base' require 'action_view/partials' @@ -37,6 +38,8 @@ require 'action_view/template_error' ActionView::Base.class_eval do include ActionView::Partials -end -ActionView::Base.load_helpers + ActionView::Base.helper_modules.each do |helper_module| + include helper_module + end +end diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index e83c8b6bd3..12dd7d2bc9 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -1,6 +1,9 @@ module ActionView #:nodoc: class ActionViewError < StandardError #:nodoc: end + + class MissingTemplate < ActionViewError #:nodoc: + end # Action View templates can be written in three ways. If the template file has a +.erb+ (or +.rhtml+) extension then it uses a mixture of ERb # (included in Ruby) and HTML. If the template file has a +.builder+ (or +.rxml+) extension then Jim Weirich's Builder::XmlMarkup library is used. @@ -202,15 +205,17 @@ module ActionView #:nodoc: class ObjectWrapper < Struct.new(:value) #:nodoc: end - def self.load_helpers #:nodoc: - Dir.entries("#{File.dirname(__FILE__)}/helpers").sort.each do |file| + def self.helper_modules #:nodoc: + helpers = [] + Dir.entries(File.expand_path("#{File.dirname(__FILE__)}/helpers")).sort.each do |file| next unless file =~ /^([a-z][a-z_]*_helper).rb$/ require "action_view/helpers/#{$1}" helper_module_name = $1.camelize if Helpers.const_defined?(helper_module_name) - include Helpers.const_get(helper_module_name) + helpers << Helpers.const_get(helper_module_name) end end + return helpers end def initialize(view_paths = [], assigns_for_first_render = {}, controller = nil)#:nodoc: @@ -279,7 +284,7 @@ If you are rendering a subtemplate, you must now use controller-like partial syn elsif options[:partial] render_partial(options[:partial], ActionView::Base::ObjectWrapper.new(options[:object]), options[:locals]) elsif options[:inline] - template = Template.new(self, options[:inline], false, options[:locals], true, options[:type]) + template = InlineTemplate.new(self, options[:inline], options[:locals], options[:type]) render_template(template) end end @@ -320,7 +325,7 @@ If you are rendering a subtemplate, you must now use controller-like partial syn end end - private + private def wrap_content_for_layout(content) original_content_for_layout = @content_for_layout @content_for_layout = content diff --git a/actionpack/lib/action_view/helpers/asset_tag_helper.rb b/actionpack/lib/action_view/helpers/asset_tag_helper.rb index d57d1e0903..0cce96b184 100644 --- a/actionpack/lib/action_view/helpers/asset_tag_helper.rb +++ b/actionpack/lib/action_view/helpers/asset_tag_helper.rb @@ -101,7 +101,7 @@ module ActionView # something like Live HTTP Headers for Firefox to verify that the cache is indeed working (and that the assets are not being # requested over and over). module AssetTagHelper - ASSETS_DIR = defined?(RAILS_ROOT) ? "#{RAILS_ROOT}/public" : "public" + ASSETS_DIR = defined?(Rails.public_path) ? Rails.public_path : "public" JAVASCRIPTS_DIR = "#{ASSETS_DIR}/javascripts" STYLESHEETS_DIR = "#{ASSETS_DIR}/stylesheets" @@ -474,7 +474,7 @@ module ActionView ActionView::Base.computed_public_paths[cache_key] ||= begin - source += ".#{ext}" if File.extname(source).blank? && ext + source += ".#{ext}" if ext && File.extname(source).blank? || File.exist?(File.join(ASSETS_DIR, dir, "#{source}.#{ext}")) if source =~ %r{^[-a-z]+://} source @@ -566,7 +566,7 @@ module ActionView def expand_javascript_sources(sources) if sources.include?(:all) - all_javascript_files = Dir[File.join(JAVASCRIPTS_DIR, '*.js')].collect { |file| File.basename(file).split(".", 0).first }.sort + all_javascript_files = Dir[File.join(JAVASCRIPTS_DIR, '*.js')].collect { |file| File.basename(file).gsub(/\.\w+$/, '') }.sort @@all_javascript_sources ||= ((determine_source(:defaults, @@javascript_expansions).dup & all_javascript_files) + all_javascript_files).uniq else expanded_sources = sources.collect do |source| @@ -579,7 +579,7 @@ module ActionView def expand_stylesheet_sources(sources) if sources.first == :all - @@all_stylesheet_sources ||= Dir[File.join(STYLESHEETS_DIR, '*.css')].collect { |file| File.basename(file).split(".", 0).first }.sort + @@all_stylesheet_sources ||= Dir[File.join(STYLESHEETS_DIR, '*.css')].collect { |file| File.basename(file).gsub(/\.\w+$/, '') }.sort else sources.collect do |source| determine_source(source, @@stylesheet_expansions) diff --git a/actionpack/lib/action_view/inline_template.rb b/actionpack/lib/action_view/inline_template.rb new file mode 100644 index 0000000000..87c012d181 --- /dev/null +++ b/actionpack/lib/action_view/inline_template.rb @@ -0,0 +1,20 @@ +module ActionView #:nodoc: + class InlineTemplate < Template #:nodoc: + + def initialize(view, source, locals = {}, type = nil) + @view = view + @finder = @view.finder + + @source = source + @extension = type + @locals = locals || {} + + @handler = self.class.handler_class_for_extension(@extension).new(@view) + end + + def method_key + @source + end + + end +end diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb index 0cd6784fd8..bc3d8d5e52 100644 --- a/actionpack/lib/action_view/template.rb +++ b/actionpack/lib/action_view/template.rb @@ -2,22 +2,18 @@ module ActionView #:nodoc: class Template #:nodoc: attr_accessor :locals - attr_reader :handler, :path, :source, :extension, :filename, :path_without_extension, :method + attr_reader :handler, :path, :extension, :filename, :path_without_extension, :method - def initialize(view, path_or_source, use_full_path, locals = {}, inline = false, inline_type = nil) + def initialize(view, path, use_full_path, locals = {}) @view = view @finder = @view.finder - unless inline - # Clear the forward slash at the beginning if exists - @path = use_full_path ? path_or_source.sub(/^\//, '') : path_or_source - @view.first_render ||= @path - @source = nil # Don't read the source until we know that it is required - set_extension_and_file_name(use_full_path) - else - @source = path_or_source - @extension = inline_type - end + # Clear the forward slash at the beginning if exists + @path = use_full_path ? path.sub(/^\//, '') : path + @view.first_render ||= @path + @source = nil # Don't read the source until we know that it is required + set_extension_and_file_name(use_full_path) + @locals = locals || {} @handler = self.class.handler_class_for_extension(@extension).new(@view) end @@ -32,7 +28,7 @@ module ActionView #:nodoc: end def method_key - @method_key ||= (@filename || @source) + @filename end def base_path_for_exception @@ -58,9 +54,8 @@ module ActionView #:nodoc: @filename = @finder.pick_template(@path_without_extension, @extension) else @extension = @finder.pick_template_extension(@path).to_s - unless @extension - raise ActionViewError, "No template found for #{@path} in #{@finder.view_paths.inspect}" - end + raise_missing_template_exception unless @extension + @filename = @finder.pick_template(@path, @extension) @extension = @extension.gsub(/^.+\./, '') # strip off any formats end @@ -68,9 +63,14 @@ module ActionView #:nodoc: @filename = @path end - if @filename.blank? - raise ActionViewError, "Couldn't find template file for #{@path} in #{@finder.view_paths.inspect}" - end + raise_missing_template_exception if @filename.blank? + end + + def raise_missing_template_exception + full_template_path = @path.include?('.') ? @path : "#{@path}.#{@view.template_format}.erb" + display_paths = @finder.view_paths.join(':') + template_type = (@path =~ /layouts/i) ? 'layout' : 'template' + raise(MissingTemplate, "Missing #{template_type} #{full_template_path} in view path #{display_paths}") end # Template Handlers diff --git a/actionpack/lib/action_view/test_case.rb b/actionpack/lib/action_view/test_case.rb new file mode 100644 index 0000000000..b2e6589d81 --- /dev/null +++ b/actionpack/lib/action_view/test_case.rb @@ -0,0 +1,64 @@ +require 'active_support/test_case' + +module ActionView + class NonInferrableHelperError < ActionViewError + def initialize(name) + super "Unable to determine the helper to test from #{name}. " + + "You'll need to specify it using tests YourHelper in your " + + "test case definition" + end + end + + class TestCase < ActiveSupport::TestCase + class_inheritable_accessor :helper_class + @@helper_class = nil + + class << self + def tests(helper_class) + self.helper_class = helper_class + end + + def helper_class + if current_helper_class = read_inheritable_attribute(:helper_class) + current_helper_class + else + self.helper_class = determine_default_helper_class(name) + end + end + + def determine_default_helper_class(name) + name.sub(/Test$/, '').constantize + rescue NameError + raise NonInferrableHelperError.new(name) + end + end + + ActionView::Base.helper_modules.each do |helper_module| + include helper_module + end + include ActionController::PolymorphicRoutes + include ActionController::RecordIdentifier + + setup :setup_with_helper_class + + def setup_with_helper_class + self.class.send(:include, helper_class) + end + + class TestController < ActionController::Base + attr_accessor :request, :response + + def initialize + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + end + end + + private + def method_missing(selector, *args) + controller = TestController.new + return controller.send!(selector, *args) if ActionController::Routing::Routes.named_routes.helpers.include?(selector) + super + end + end +end |