diff options
author | Emilio Tagua <miloops@gmail.com> | 2009-06-23 18:13:46 -0300 |
---|---|---|
committer | Emilio Tagua <miloops@gmail.com> | 2009-06-23 18:13:46 -0300 |
commit | b9088dce07f8525cdb84a1312a77b81db79067d6 (patch) | |
tree | 72ace069842b074981ba814ef1c335271176ce27 /actionpack/lib | |
parent | 4864f92ee34e840307d968fa8b04972b6d786fe8 (diff) | |
parent | 4417a19b035d73eb46a5e06e296a4b1c8091bef1 (diff) | |
download | rails-b9088dce07f8525cdb84a1312a77b81db79067d6.tar.gz rails-b9088dce07f8525cdb84a1312a77b81db79067d6.tar.bz2 rails-b9088dce07f8525cdb84a1312a77b81db79067d6.zip |
Merge commit 'rails/master'
Diffstat (limited to 'actionpack/lib')
27 files changed, 337 insertions, 415 deletions
diff --git a/actionpack/lib/action_controller/base/compatibility.rb b/actionpack/lib/action_controller/base/compatibility.rb index 29ba43a879..cd4b72b1c6 100644 --- a/actionpack/lib/action_controller/base/compatibility.rb +++ b/actionpack/lib/action_controller/base/compatibility.rb @@ -118,6 +118,14 @@ module ActionController details[:prefix] = nil if name =~ /\blayouts/ super end + + # Move this into a "don't run in production" module + def _default_layout(details, require_layout = false) + super + rescue ActionView::MissingTemplate + _find_by_parts(_layout({}), {}) + nil + end def performed? response_body diff --git a/actionpack/lib/action_controller/base/filter_parameter_logging.rb b/actionpack/lib/action_controller/base/filter_parameter_logging.rb index 8370ba6fc0..26cd03f277 100644 --- a/actionpack/lib/action_controller/base/filter_parameter_logging.rb +++ b/actionpack/lib/action_controller/base/filter_parameter_logging.rb @@ -2,10 +2,7 @@ module ActionController module FilterParameterLogging extend ActiveSupport::Concern - # TODO : Remove the defined? check when new base is the main base - if defined?(ActionController::Http) - include AbstractController::Logger - end + include AbstractController::Logger included do include InstanceMethodsForNewBase diff --git a/actionpack/lib/action_controller/base/flash.rb b/actionpack/lib/action_controller/base/flash.rb index 42c6e430ca..590f9be3ac 100644 --- a/actionpack/lib/action_controller/base/flash.rb +++ b/actionpack/lib/action_controller/base/flash.rb @@ -28,20 +28,7 @@ module ActionController #:nodoc: module Flash extend ActiveSupport::Concern - # TODO : Remove the defined? check when new base is the main base - include Session if defined?(ActionController::Http) - - included do - # TODO : Remove the defined? check when new base is the main base - if defined?(ActionController::Http) - include InstanceMethodsForNewBase - else - include InstanceMethodsForBase - - alias_method_chain :perform_action, :flash - alias_method_chain :reset_session, :flash - end - end + include Session class FlashNow #:nodoc: def initialize(flash) @@ -148,49 +135,30 @@ module ActionController #:nodoc: end end - module InstanceMethodsForBase #:nodoc: - protected - def perform_action_with_flash - perform_action_without_flash - if defined? @_flash - @_flash.store(session) - remove_instance_variable(:@_flash) - end - end - - def reset_session_with_flash - reset_session_without_flash - remove_instance_variable(:@_flash) if defined?(@_flash) - end + protected + def process_action(method_name) + super + if defined? @_flash + @_flash.store(session) + remove_instance_variable(:@_flash) + end end - module InstanceMethodsForNewBase #:nodoc: - protected - def process_action(method_name) - super - if defined? @_flash - @_flash.store(session) - remove_instance_variable(:@_flash) - end - end - - def reset_session - super - remove_instance_variable(:@_flash) if defined?(@_flash) - end + def reset_session + super + remove_instance_variable(:@_flash) if defined?(@_flash) end - protected - # Access the contents of the flash. Use <tt>flash["notice"]</tt> to - # read a notice you put there or <tt>flash["notice"] = "hello"</tt> - # to put a new one. - def flash #:doc: - if !defined?(@_flash) - @_flash = session["flash"] || FlashHash.new - @_flash.sweep - end - - @_flash + # Access the contents of the flash. Use <tt>flash["notice"]</tt> to + # read a notice you put there or <tt>flash["notice"] = "hello"</tt> + # to put a new one. + def flash #:doc: + if !defined?(@_flash) + @_flash = session["flash"] || FlashHash.new + @_flash.sweep end + + @_flash + end end end diff --git a/actionpack/lib/action_controller/base/http.rb b/actionpack/lib/action_controller/base/http.rb index 2e73561f93..ec78bc15a8 100644 --- a/actionpack/lib/action_controller/base/http.rb +++ b/actionpack/lib/action_controller/base/http.rb @@ -36,7 +36,7 @@ module ActionController # ==== Returns # String def self.controller_path - @controller_path ||= self.name.sub(/Controller$/, '').underscore + @controller_path ||= name && name.sub(/Controller$/, '').underscore end # Delegates to the class' #controller_path diff --git a/actionpack/lib/action_controller/base/layouts.rb b/actionpack/lib/action_controller/base/layouts.rb index ace4b148c9..365351b421 100644 --- a/actionpack/lib/action_controller/base/layouts.rb +++ b/actionpack/lib/action_controller/base/layouts.rb @@ -26,9 +26,6 @@ module ActionController # hello world # // The footer part of this layout # - # NOTE: The old notation for rendering the view from a layout was to expose the magic <tt>@content_for_layout</tt> instance - # variable. The preferred notation now is to use <tt>yield</tt>, as documented above. - # # == Accessing shared variables # # Layouts have access to variables specified in the content pages and vice versa. This allows you to have layouts with @@ -176,7 +173,7 @@ module ActionController super return if (options.key?(:text) || options.key?(:inline) || options.key?(:partial)) && !options.key?(:layout) - layout = options.key?(:layout) ? options[:layout] : :none + layout = options.key?(:layout) ? options[:layout] : :default options[:_layout] = _layout_for_option(layout, options[:_template].details) end @@ -184,7 +181,7 @@ module ActionController case name when String then _layout_for_name(name, details) when true then _default_layout(details, true) - when :none then _default_layout(details, false) + when :default then _default_layout(details, false) when false, nil then nil else raise ArgumentError, diff --git a/actionpack/lib/action_controller/base/mime_responds.rb b/actionpack/lib/action_controller/base/mime_responds.rb index 5c7218691e..ed0d58dba1 100644 --- a/actionpack/lib/action_controller/base/mime_responds.rb +++ b/actionpack/lib/action_controller/base/mime_responds.rb @@ -120,12 +120,9 @@ module ActionController #:nodoc: @responses[mime_type] ||= Proc.new do # TODO: Remove this when new base is merged in - if defined?(Http) - @controller.formats = [mime_type.to_sym] - end - + @controller.formats = [mime_type.to_sym] + @controller.content_type = mime_type @controller.template.formats = [mime_type.to_sym] - @response.content_type = mime_type block_given? ? block.call : @controller.send(:render, :action => @controller.action_name) end diff --git a/actionpack/lib/action_controller/base/request_forgery_protection.rb b/actionpack/lib/action_controller/base/request_forgery_protection.rb index a470c8eec1..6ba86cd0be 100644 --- a/actionpack/lib/action_controller/base/request_forgery_protection.rb +++ b/actionpack/lib/action_controller/base/request_forgery_protection.rb @@ -6,20 +6,16 @@ module ActionController #:nodoc: extend ActiveSupport::Concern # TODO : Remove the defined? check when new base is the main base - if defined?(ActionController::Http) - include AbstractController::Helpers, Session - end + include AbstractController::Helpers, Session included do - if defined?(ActionController::Http) - # Sets the token parameter name for RequestForgery. Calling +protect_from_forgery+ - # sets it to <tt>:authenticity_token</tt> by default. - cattr_accessor :request_forgery_protection_token + # Sets the token parameter name for RequestForgery. Calling +protect_from_forgery+ + # sets it to <tt>:authenticity_token</tt> by default. + cattr_accessor :request_forgery_protection_token - # Controls whether request forgergy protection is turned on or not. Turned off by default only in test mode. - class_inheritable_accessor :allow_forgery_protection - self.allow_forgery_protection = true - end + # Controls whether request forgergy protection is turned on or not. Turned off by default only in test mode. + class_inheritable_accessor :allow_forgery_protection + self.allow_forgery_protection = true helper_method :form_authenticity_token helper_method :protect_against_forgery? diff --git a/actionpack/lib/action_controller/base/streaming.rb b/actionpack/lib/action_controller/base/streaming.rb index 5c72fc9ad9..70a97ccfec 100644 --- a/actionpack/lib/action_controller/base/streaming.rb +++ b/actionpack/lib/action_controller/base/streaming.rb @@ -4,10 +4,7 @@ module ActionController #:nodoc: module Streaming extend ActiveSupport::Concern - # TODO : Remove the defined? check when new base is the main base - if defined?(ActionController::Http) - include ActionController::Renderer - end + include ActionController::Renderer DEFAULT_SEND_FILE_OPTIONS = { :type => 'application/octet-stream'.freeze, diff --git a/actionpack/lib/action_controller/base/verification.rb b/actionpack/lib/action_controller/base/verification.rb index d87b348ed4..951ae1bee1 100644 --- a/actionpack/lib/action_controller/base/verification.rb +++ b/actionpack/lib/action_controller/base/verification.rb @@ -2,10 +2,7 @@ module ActionController #:nodoc: module Verification #:nodoc: extend ActiveSupport::Concern - # TODO : Remove the defined? check when new base is the main base - if defined?(ActionController::Http) - include AbstractController::Callbacks, Session, Flash, Renderer - end + include AbstractController::Callbacks, Session, Flash, Renderer # This module provides a class-level method for specifying that certain # actions are guarded against being called without certain prerequisites diff --git a/actionpack/lib/action_controller/caching/actions.rb b/actionpack/lib/action_controller/caching/actions.rb index 54148b55d8..d8a1662acc 100644 --- a/actionpack/lib/action_controller/caching/actions.rb +++ b/actionpack/lib/action_controller/caching/actions.rb @@ -62,14 +62,7 @@ module ActionController #:nodoc: cache_filter = ActionCacheFilter.new(:layout => options.delete(:layout), :cache_path => options.delete(:cache_path), :store_options => options) - # TODO: Remove this once new base is swapped in. - if defined?(ActionController::Http) - around_filter cache_filter, filter_options - else - around_filter(filter_options) do |controller, action| - cache_filter.filter(controller, action) - end - end + around_filter cache_filter, filter_options end end @@ -91,19 +84,10 @@ module ActionController #:nodoc: @options = options end - # TODO: Remove once New Base is merged - if defined?(ActionController::Http) - def filter(controller) - should_continue = before(controller) - yield if should_continue - after(controller) - end - else - def filter(controller, action) - should_continue = before(controller) - action.call if should_continue - after(controller) - end + def filter(controller) + should_continue = before(controller) + yield if should_continue + after(controller) end def before(controller) diff --git a/actionpack/lib/action_controller/legacy/layout.rb b/actionpack/lib/action_controller/legacy/layout.rb index 3046e082d9..3f3d20b95f 100644 --- a/actionpack/lib/action_controller/legacy/layout.rb +++ b/actionpack/lib/action_controller/legacy/layout.rb @@ -44,9 +44,6 @@ module ActionController #:nodoc: # hello world # // The footer part of this layout # - # NOTE: The old notation for rendering the view from a layout was to expose the magic <tt>@content_for_layout</tt> instance - # variable. The preferred notation now is to use <tt>yield</tt>, as documented above. - # # == Accessing shared variables # # Layouts have access to variables specified in the content pages and vice versa. This allows you to have layouts with diff --git a/actionpack/lib/action_controller/routing/generation/polymorphic_routes.rb b/actionpack/lib/action_controller/routing/generation/polymorphic_routes.rb index d9b614c237..c6f7de17bd 100644 --- a/actionpack/lib/action_controller/routing/generation/polymorphic_routes.rb +++ b/actionpack/lib/action_controller/routing/generation/polymorphic_routes.rb @@ -112,8 +112,7 @@ module ActionController # Returns the path component of a URL for the given record. It uses # <tt>polymorphic_url</tt> with <tt>:routing_type => :path</tt>. def polymorphic_path(record_or_hash_or_array, options = {}) - options[:routing_type] = :path - polymorphic_url(record_or_hash_or_array, options) + polymorphic_url(record_or_hash_or_array, options.merge(:routing_type => :path)) end %w(edit new).each do |action| diff --git a/actionpack/lib/action_dispatch/http/mime_type.rb b/actionpack/lib/action_dispatch/http/mime_type.rb index 25156a4c75..27f27e27fe 100644 --- a/actionpack/lib/action_dispatch/http/mime_type.rb +++ b/actionpack/lib/action_dispatch/http/mime_type.rb @@ -2,7 +2,19 @@ require 'set' require 'active_support/core_ext/class/attribute_accessors' module Mime - SET = [] + class Mimes < Array + def symbols + @symbols ||= map {|m| m.to_sym } + end + + %w(<< concat shift unshift push pop []= clear compact! collect! + delete delete_at delete_if flatten! map! insert reject! reverse! + replace slice! sort! uniq!).each do |method| + define_method(method) {|*args| @symbols = nil; super(*args) } + end + end + + SET = Mimes.new EXTENSION_LOOKUP = {} LOOKUP = Hash.new { |h, k| h[k] = Type.new(k) unless k.blank? } diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb index 140feb9a68..3f23a5af7a 100755 --- a/actionpack/lib/action_dispatch/http/request.rb +++ b/actionpack/lib/action_dispatch/http/request.rb @@ -180,12 +180,10 @@ module ActionDispatch else accepts.dup end.tap do |ret| - if defined?(ActionController::Http) - if ret == ONLY_ALL - ret.replace Mime::SET - elsif all = ret.index(Mime::ALL) - ret.delete_at(all) && ret.insert(all, *Mime::SET) - end + if ret == ONLY_ALL + ret.replace Mime::SET + elsif all = ret.index(Mime::ALL) + ret.delete_at(all) && ret.insert(all, *Mime::SET) end end else diff --git a/actionpack/lib/action_view.rb b/actionpack/lib/action_view.rb index 94138097e3..27a06db5bb 100644 --- a/actionpack/lib/action_view.rb +++ b/actionpack/lib/action_view.rb @@ -33,21 +33,22 @@ module ActionView [Base, InlineTemplate, TemplateError] end - autoload :Base, 'action_view/base' - autoload :Helpers, 'action_view/helpers' - autoload :InlineTemplate, 'action_view/template/inline' - autoload :Partials, 'action_view/render/partials' - autoload :Path, 'action_view/template/path' - autoload :PathSet, 'action_view/paths' - autoload :Rendering, 'action_view/render/rendering' - autoload :Renderable, 'action_view/template/renderable' + autoload :Base, 'action_view/base' + autoload :Helpers, 'action_view/helpers' + autoload :InlineTemplate, 'action_view/template/inline' + autoload :Partials, 'action_view/render/partials' + autoload :Resolver, 'action_view/template/resolver' + autoload :PathSet, 'action_view/paths' + autoload :Rendering, 'action_view/render/rendering' + autoload :Renderable, 'action_view/template/renderable' autoload :RenderablePartial, 'action_view/template/partial' - autoload :Template, 'action_view/template/template' - autoload :TemplateError, 'action_view/template/error' - autoload :TemplateHandler, 'action_view/template/handler' - autoload :TemplateHandlers, 'action_view/template/handlers' - autoload :TextTemplate, 'action_view/template/text' - autoload :Helpers, 'action_view/helpers' + autoload :Template, 'action_view/template/template' + autoload :TemplateError, 'action_view/template/error' + autoload :TemplateHandler, 'action_view/template/handler' + autoload :TemplateHandlers, 'action_view/template/handlers' + autoload :TextTemplate, 'action_view/template/text' + autoload :Helpers, 'action_view/helpers' + autoload :FileSystemResolverWithFallback, 'action_view/template/resolver' end class ERB diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index 4ab568b44c..45184f58fb 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -170,12 +170,13 @@ module ActionView #:nodoc: attr_accessor :base_path, :assigns, :template_extension, :formats attr_accessor :controller + attr_internal :captures attr_accessor :output_buffer class << self delegate :erb_trim_mode=, :to => 'ActionView::TemplateHandlers::ERB' - delegate :logger, :to => 'ActionController::Base' + delegate :logger, :to => 'ActionController::Base', :allow_nil => true end @@debug_rjs = false @@ -229,38 +230,27 @@ module ActionView #:nodoc: def initialize(view_paths = [], assigns_for_first_render = {}, controller = nil, formats = nil)#:nodoc: @formats = formats || [:html] - @assigns = assigns_for_first_render - @assigns_added = nil + @assigns = assigns_for_first_render.each { |key, value| instance_variable_set("@#{key}", value) } @controller = controller @helpers = ProxyModule.new(self) + @_content_for = Hash.new {|h,k| h[k] = "" } self.view_paths = view_paths - - @_first_render = nil - @_current_render = nil end + attr_internal :template attr_reader :view_paths def view_paths=(paths) @view_paths = self.class.process_view_paths(paths) end - # Access the current template being rendered. - # Returns a ActionView::Template object. - def template - @_current_render - end - - def template=(template) #:nodoc: - @_first_render ||= template - @_current_render = template - end - def with_template(current_template) + _evaluate_assigns_and_ivars last_template, self.template = template, current_template + last_formats, self.formats = formats, [current_template.mime_type.to_sym] + Mime::SET.symbols yield ensure - self.template = last_template + self.template, self.formats = last_template, last_formats end def punctuate_body!(part) @@ -271,30 +261,19 @@ module ActionView #:nodoc: # Evaluates the local assigns and controller ivars, pushes them to the view. def _evaluate_assigns_and_ivars #:nodoc: - unless @assigns_added - @assigns.each { |key, value| instance_variable_set("@#{key}", value) } - _copy_ivars_from_controller - @assigns_added = true - end + @assigns_added ||= _copy_ivars_from_controller end - private + private - def _copy_ivars_from_controller #:nodoc: - if @controller - variables = @controller.instance_variable_names - variables -= @controller.protected_instance_variables if @controller.respond_to?(:protected_instance_variables) - variables.each { |name| instance_variable_set(name, @controller.instance_variable_get(name)) } - end + def _copy_ivars_from_controller #:nodoc: + if @controller + variables = @controller.instance_variable_names + variables -= @controller.protected_instance_variables if @controller.respond_to?(:protected_instance_variables) + variables.each { |name| instance_variable_set(name, @controller.instance_variable_get(name)) } end + true + end - def _set_controller_content_type(content_type) #:nodoc: - # TODO: Remove this method when new base is switched - unless defined?(ActionController::Http) - if controller.respond_to?(:response) - controller.response.content_type ||= content_type - end - end - end end end diff --git a/actionpack/lib/action_view/helpers/active_record_helper.rb b/actionpack/lib/action_view/helpers/active_record_helper.rb index 8b70200654..75cc651968 100644 --- a/actionpack/lib/action_view/helpers/active_record_helper.rb +++ b/actionpack/lib/action_view/helpers/active_record_helper.rb @@ -122,9 +122,9 @@ module ActionView options.reverse_merge!(:prepend_text => '', :append_text => '', :css_class => 'formError') if (obj = (object.respond_to?(:errors) ? object : instance_variable_get("@#{object}"))) && - (errors = obj.errors.on(method)) + (errors = obj.errors[method]) content_tag("div", - "#{options[:prepend_text]}#{ERB::Util.html_escape(errors.is_a?(Array) ? errors.first : errors)}#{options[:append_text]}", + "#{options[:prepend_text]}#{ERB::Util.html_escape(errors.first)}#{options[:append_text]}", :class => options[:css_class] ) else @@ -247,59 +247,22 @@ module ActionView end end - alias_method :tag_without_error_wrapping, :tag - def tag(name, options) - if object.respond_to?(:errors) && object.errors.respond_to?(:on) - error_wrapping(tag_without_error_wrapping(name, options), object.errors.on(@method_name)) - else - tag_without_error_wrapping(name, options) - end - end - - alias_method :content_tag_without_error_wrapping, :content_tag - def content_tag(name, value, options) - if object.respond_to?(:errors) && object.errors.respond_to?(:on) - error_wrapping(content_tag_without_error_wrapping(name, value, options), object.errors.on(@method_name)) - else - content_tag_without_error_wrapping(name, value, options) - end - end - - alias_method :to_date_select_tag_without_error_wrapping, :to_date_select_tag - def to_date_select_tag(options = {}, html_options = {}) - if object.respond_to?(:errors) && object.errors.respond_to?(:on) - error_wrapping(to_date_select_tag_without_error_wrapping(options, html_options), object.errors.on(@method_name)) - else - to_date_select_tag_without_error_wrapping(options, html_options) - end - end - - alias_method :to_datetime_select_tag_without_error_wrapping, :to_datetime_select_tag - def to_datetime_select_tag(options = {}, html_options = {}) - if object.respond_to?(:errors) && object.errors.respond_to?(:on) - error_wrapping(to_datetime_select_tag_without_error_wrapping(options, html_options), object.errors.on(@method_name)) - else - to_datetime_select_tag_without_error_wrapping(options, html_options) + %w(tag content_tag to_date_select_tag to_datetime_select_tag to_time_select_tag).each do |meth| + without = "#{meth}_without_error_wrapping" + define_method "#{meth}_with_error_wrapping" do |*args| + error_wrapping(send(without, *args)) end + alias_method_chain meth, :error_wrapping end - alias_method :to_time_select_tag_without_error_wrapping, :to_time_select_tag - def to_time_select_tag(options = {}, html_options = {}) - if object.respond_to?(:errors) && object.errors.respond_to?(:on) - error_wrapping(to_time_select_tag_without_error_wrapping(options, html_options), object.errors.on(@method_name)) + def error_wrapping(html_tag) + if object.respond_to?(:errors) && object.errors.respond_to?(:full_messages) && object.errors[@method_name].any? + Base.field_error_proc.call(html_tag, self) else - to_time_select_tag_without_error_wrapping(options, html_options) + html_tag end end - def error_wrapping(html_tag, has_error) - has_error ? Base.field_error_proc.call(html_tag, self) : html_tag - end - - def error_message - object.errors.on(@method_name) - end - def column_type object.send(:column_for_attribute, @method_name).type end diff --git a/actionpack/lib/action_view/helpers/capture_helper.rb b/actionpack/lib/action_view/helpers/capture_helper.rb index b4197479a0..c90acc5ac2 100644 --- a/actionpack/lib/action_view/helpers/capture_helper.rb +++ b/actionpack/lib/action_view/helpers/capture_helper.rb @@ -111,15 +111,32 @@ module ActionView # # WARNING: content_for is ignored in caches. So you shouldn't use it # for elements that will be fragment cached. - # - # The deprecated way of accessing a content_for block is to use an instance variable - # named <tt>@content_for_#{name_of_the_content_block}</tt>. The preferred usage is now - # <tt><%= yield :footer %></tt>. def content_for(name, content = nil, &block) - ivar = "@content_for_#{name}" content = capture(&block) if block_given? - instance_variable_set(ivar, "#{instance_variable_get(ivar)}#{content}") - nil + return @_content_for[name] << content if content + @_content_for[name] + end + + # content_for? simply checks whether any content has been captured yet using content_for + # Useful to render parts of your layout differently based on what is in your views. + # + # ==== Examples + # + # Perhaps you will use different css in you layout if no content_for :right_column + # + # <%# This is the layout %> + # <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> + # <head> + # <title>My Website</title> + # <%= yield :script %> + # </head> + # <body class="<%= content_for?(:right_col) ? 'one-column' : 'two-column' %>"> + # <%= yield %> + # <%= yield :right_col %> + # </body> + # </html> + def content_for?(name) + @_content_for[name].present? end # Use an alternate output buffer for the duration of the block. diff --git a/actionpack/lib/action_view/paths.rb b/actionpack/lib/action_view/paths.rb index 95c56faf9c..074b475819 100644 --- a/actionpack/lib/action_view/paths.rb +++ b/actionpack/lib/action_view/paths.rb @@ -3,7 +3,7 @@ module ActionView #:nodoc: def self.type_cast(obj) if obj.is_a?(String) cache = !defined?(Rails) || !Rails.respond_to?(:configuration) || Rails.configuration.cache_classes - Template::FileSystemPathWithFallback.new(obj, :cache => cache) + FileSystemResolverWithFallback.new(obj, :cache => cache) else obj end diff --git a/actionpack/lib/action_view/render/partials.rb b/actionpack/lib/action_view/render/partials.rb index eacf117bea..87314fff67 100644 --- a/actionpack/lib/action_view/render/partials.rb +++ b/actionpack/lib/action_view/render/partials.rb @@ -245,13 +245,6 @@ module ActionView end end - def _render_partial_with_block(layout, block, options) - @_proc_for_layout = block - concat(_render_partial(options.merge(:partial => layout))) - ensure - @_proc_for_layout = nil - end - def _render_partial_with_layout(layout, options) if layout prefix = controller && !layout.include?("/") ? controller.controller_path : nil diff --git a/actionpack/lib/action_view/render/rendering.rb b/actionpack/lib/action_view/render/rendering.rb index fe785e7b20..162e38c484 100644 --- a/actionpack/lib/action_view/render/rendering.rb +++ b/actionpack/lib/action_view/render/rendering.rb @@ -51,32 +51,60 @@ module ActionView end begin - original_content_for_layout = @content_for_layout if defined?(@content_for_layout) - @content_for_layout = content + old_content, @_content_for[:layout] = @_content_for[:layout], content - @cached_content_for_layout = @content_for_layout + @cached_content_for_layout = @_content_for[:layout] _render_template(layout, locals) ensure - @content_for_layout = original_content_for_layout + @_content_for[:layout] = old_content end end + # You can think of a layout as a method that is called with a block. This method + # returns the block that the layout is called with. If the user calls yield :some_name, + # the block, by default, returns content_for(:some_name). If the user calls yield, + # the default block returns content_for(:layout). + # + # The user can override this default by passing a block to the layout. + # + # ==== Example + # + # # The template + # <% render :layout => "my_layout" do %>Content<% end %> + # + # # The layout + # <html><% yield %></html> + # + # In this case, instead of the default block, which would return content_for(:layout), + # this method returns the block that was passed in to render layout, and the response + # would be <html>Content</html>. + # + # Finally, the block can take block arguments, which can be passed in by yield. + # + # ==== Example + # + # # The template + # <% render :layout => "my_layout" do |customer| %>Hello <%= customer.name %><% end %> + # + # # The layout + # <html><% yield Struct.new(:name).new("David") %></html> + # + # In this case, the layout would receive the block passed into <tt>render :layout</tt>, + # and the Struct specified in the layout would be passed into the block. The result + # would be <html>Hello David</html>. + def layout_proc(name) + @_default_layout ||= proc { |*names| @_content_for[names.first || :layout] } + !@_content_for.key?(name) && @_proc_for_layout || @_default_layout + end + def _render_template(template, local_assigns = {}) with_template(template) do - _evaluate_assigns_and_ivars - _set_controller_content_type(template.mime_type) if template.respond_to?(:mime_type) - template.render(self, local_assigns) do |*names| - if !instance_variable_defined?(:"@content_for_#{names.first}") && - instance_variable_defined?(:@_proc_for_layout) && (proc = @_proc_for_layout) - capture(*names, &proc) - elsif instance_variable_defined?(ivar = :"@content_for_#{names.first || :layout}") - instance_variable_get(ivar) - end + capture(*names, &layout_proc(names.first)) end end rescue Exception => e - if TemplateError === e + if e.is_a?(TemplateError) e.sub_template_of(template) raise e else @@ -101,20 +129,18 @@ module ActionView end def _render_template_with_layout(template, layout = nil, options = {}, partial = false) - if controller && logger - logger.info("Rendering #{template.identifier}" + - (options[:status] ? " (#{options[:status]})" : '')) - end - + logger && logger.info("Rendering #{template.identifier}#{' (#{options[:status]})' if options[:status]}") + + locals = options[:locals] || {} + content = if partial object = partial unless partial == true _render_partial_object(template, options, object) else - _render_template(template, options[:locals] || {}) + _render_template(template, locals) end - return content unless layout - _render_content_with_layout(content, layout, options[:locals] || {}) + layout ? _render_content_with_layout(content, layout, locals) : content end end end
\ No newline at end of file diff --git a/actionpack/lib/action_view/template/handlers/builder.rb b/actionpack/lib/action_view/template/handlers/builder.rb index f412228752..abe140af0b 100644 --- a/actionpack/lib/action_view/template/handlers/builder.rb +++ b/actionpack/lib/action_view/template/handlers/builder.rb @@ -8,8 +8,7 @@ module ActionView self.default_format = Mime::XML def compile(template) - "_set_controller_content_type(Mime::XML);" + - "xml = ::Builder::XmlMarkup.new(:indent => 2);" + + "xml = ::Builder::XmlMarkup.new(:indent => 2);" + "self.output_buffer = xml.target!;" + template.source + ";xml.target!;" diff --git a/actionpack/lib/action_view/template/handlers/rjs.rb b/actionpack/lib/action_view/template/handlers/rjs.rb index a36744c2b7..b1d15dc209 100644 --- a/actionpack/lib/action_view/template/handlers/rjs.rb +++ b/actionpack/lib/action_view/template/handlers/rjs.rb @@ -6,7 +6,6 @@ module ActionView self.default_format = Mime::JS def compile(template) - "@formats = [:html];" + "controller.response.content_type ||= Mime::JS;" + "update_page do |page|;#{template.source}\nend" end diff --git a/actionpack/lib/action_view/template/path.rb b/actionpack/lib/action_view/template/path.rb deleted file mode 100644 index 478bf96c9a..0000000000 --- a/actionpack/lib/action_view/template/path.rb +++ /dev/null @@ -1,152 +0,0 @@ -require "pathname" - -module ActionView - class Template - # Abstract super class - class Path - def initialize(options) - @cache = options[:cache] - @cached = {} - end - - # Normalizes the arguments and passes it on to find_template - def find_by_parts(*args) - find_all_by_parts(*args).first - end - - def find_all_by_parts(name, details = {}, prefix = nil, partial = nil) - details[:locales] = [I18n.locale] - name = name.to_s.gsub(handler_matcher, '').split("/") - find_templates(name.pop, details, [prefix, *name].compact.join("/"), partial) - end - - private - - # This is what child classes implement. No defaults are needed - # because Path guarentees that the arguments are present and - # normalized. - def find_templates(name, details, prefix, partial) - raise NotImplementedError - end - - def valid_handlers - @valid_handlers ||= TemplateHandlers.extensions - end - - def handler_matcher - @handler_matcher ||= begin - e = valid_handlers.join('|') - /\.(?:#{e})$/ - end - end - - def handler_glob - e = TemplateHandlers.extensions.map{|h| ".#{h},"}.join - "{#{e}}" - end - - def formats_glob - @formats_glob ||= begin - formats = Mime::SET.map { |m| m.symbol } - '{' + formats.map { |l| ".#{l}," }.join + '}' - end - end - - def cached(key) - return yield unless @cache - return @cached[key] if @cached.key?(key) - @cached[key] = yield - end - end - - class FileSystemPath < Path - - def initialize(path, options = {}) - raise ArgumentError, "path already is a Path class" if path.is_a?(Path) - super(options) - @path = Pathname.new(path).expand_path - end - - # TODO: This is the currently needed API. Make this suck less - # ==== <suck> - attr_reader :path - - def to_s - path.to_s - end - - def to_str - path.to_s - end - - def ==(path) - to_str == path.to_str - end - - def eql?(path) - to_str == path.to_str - end - # ==== </suck> - - def find_templates(name, details, prefix, partial, root = "#{@path}/") - if glob = details_to_glob(name, details, prefix, partial, root) - cached(glob) do - Dir[glob].map do |path| - next if File.directory?(path) - source = File.read(path) - identifier = Pathname.new(path).expand_path.to_s - - Template.new(source, identifier, *path_to_details(path)) - end.compact - end - end - end - - private - - # :api: plugin - def details_to_glob(name, details, prefix, partial, root) - path = "" - path << "#{prefix}/" unless prefix.empty? - path << (partial ? "_#{name}" : name) - - extensions = "" - [:locales, :formats].each do |k| - extensions << if exts = details[k] - '{' + exts.map {|e| ".#{e},"}.join + '}' - else - k == :formats ? formats_glob : '' - end - end - - "#{root}#{path}#{extensions}#{handler_glob}" - end - - # TODO: fix me - # :api: plugin - def path_to_details(path) - # [:erb, :format => :html, :locale => :en, :partial => true/false] - if m = path.match(%r'/(_)?[\w-]+(\.[\w-]+)*\.(\w+)$') - partial = m[1] == '_' - details = (m[2]||"").split('.').reject { |e| e.empty? } - handler = Template.handler_class_for_extension(m[3]) - - format = Mime[details.last] && details.pop.to_sym - locale = details.last && details.pop.to_sym - - return handler, :format => format, :locale => locale, :partial => partial - end - end - end - - class FileSystemPathWithFallback < FileSystemPath - - def find_templates(name, details, prefix, partial) - templates = super - return super(name, details, prefix, partial, '') if templates.empty? - templates - end - - end - end -end
\ No newline at end of file diff --git a/actionpack/lib/action_view/template/resolver.rb b/actionpack/lib/action_view/template/resolver.rb new file mode 100644 index 0000000000..d15f53a11b --- /dev/null +++ b/actionpack/lib/action_view/template/resolver.rb @@ -0,0 +1,150 @@ +require "pathname" +require "action_view/template/template" + +module ActionView + # Abstract superclass + class Resolver + def initialize(options) + @cache = options[:cache] + @cached = {} + end + + # Normalizes the arguments and passes it on to find_template + def find_by_parts(*args) + find_all_by_parts(*args).first + end + + def find_all_by_parts(name, details = {}, prefix = nil, partial = nil) + details[:locales] = [I18n.locale] + name = name.to_s.gsub(handler_matcher, '').split("/") + find_templates(name.pop, details, [prefix, *name].compact.join("/"), partial) + end + + private + + # This is what child classes implement. No defaults are needed + # because Resolver guarantees that the arguments are present and + # normalized. + def find_templates(name, details, prefix, partial) + raise NotImplementedError + end + + def valid_handlers + @valid_handlers ||= TemplateHandlers.extensions + end + + def handler_matcher + @handler_matcher ||= begin + e = valid_handlers.join('|') + /\.(?:#{e})$/ + end + end + + def handler_glob + e = TemplateHandlers.extensions.map{|h| ".#{h},"}.join + "{#{e}}" + end + + def formats_glob + @formats_glob ||= begin + '{' + Mime::SET.symbols.map { |l| ".#{l}," }.join + '}' + end + end + + def cached(key) + return yield unless @cache + return @cached[key] if @cached.key?(key) + @cached[key] = yield + end + end + + class FileSystemResolver < Resolver + + def initialize(path, options = {}) + raise ArgumentError, "path already is a Resolver class" if path.is_a?(Resolver) + super(options) + @path = Pathname.new(path).expand_path + end + + # TODO: This is the currently needed API. Make this suck less + # ==== <suck> + attr_reader :path + + def to_s + path.to_s + end + + def to_str + path.to_s + end + + def ==(path) + to_str == path.to_str + end + + def eql?(path) + to_str == path.to_str + end + # ==== </suck> + + def find_templates(name, details, prefix, partial, root = "#{@path}/") + if glob = details_to_glob(name, details, prefix, partial, root) + cached(glob) do + Dir[glob].map do |path| + next if File.directory?(path) + source = File.read(path) + identifier = Pathname.new(path).expand_path.to_s + + Template.new(source, identifier, *path_to_details(path)) + end.compact + end + end + end + + private + + # :api: plugin + def details_to_glob(name, details, prefix, partial, root) + path = "" + path << "#{prefix}/" unless prefix.empty? + path << (partial ? "_#{name}" : name) + + extensions = "" + [:locales, :formats].each do |k| + extensions << if exts = details[k] + '{' + exts.map {|e| ".#{e},"}.join + '}' + else + k == :formats ? formats_glob : '' + end + end + + "#{root}#{path}#{extensions}#{handler_glob}" + end + + # TODO: fix me + # :api: plugin + def path_to_details(path) + # [:erb, :format => :html, :locale => :en, :partial => true/false] + if m = path.match(%r'/(_)?[\w-]+(\.[\w-]+)*\.(\w+)$') + partial = m[1] == '_' + details = (m[2]||"").split('.').reject { |e| e.empty? } + handler = Template.handler_class_for_extension(m[3]) + + format = Mime[details.last] && details.pop.to_sym + locale = details.last && details.pop.to_sym + + return handler, :format => format, :locale => locale, :partial => partial + end + end + end + + class FileSystemResolverWithFallback < FileSystemResolver + + def find_templates(name, details, prefix, partial) + templates = super + return super(name, details, prefix, partial, '') if templates.empty? + templates + end + + end +end
\ No newline at end of file diff --git a/actionpack/lib/action_view/template/template.rb b/actionpack/lib/action_view/template/template.rb index e7ea42c2eb..fac50cd692 100644 --- a/actionpack/lib/action_view/template/template.rb +++ b/actionpack/lib/action_view/template/template.rb @@ -2,7 +2,7 @@ # This is so that templates compiled in this file are UTF-8 require 'set' -require "action_view/template/path" +require "action_view/template/resolver" module ActionView class Template @@ -20,7 +20,7 @@ module ActionView handler.respond_to?(:default_format) ? handler.default_format.to_sym.to_s : "html" end @mime_type = Mime::Type.lookup_by_extension(format.to_s) - @details[:formats] = Array.wrap(format && format.to_sym) + @details[:formats] = Array.wrap(format.to_sym) end def render(view, locals, &blk) diff --git a/actionpack/lib/action_view/template/text.rb b/actionpack/lib/action_view/template/text.rb index fd57b1677e..81944ff546 100644 --- a/actionpack/lib/action_view/template/text.rb +++ b/actionpack/lib/action_view/template/text.rb @@ -3,7 +3,7 @@ module ActionView #:nodoc: def initialize(string, content_type = Mime[:html]) super(string.to_s) - @content_type = Mime[content_type] + @content_type = Mime[content_type] || content_type end def details |