diff options
Diffstat (limited to 'actionpack')
29 files changed, 621 insertions, 853 deletions
diff --git a/actionpack/lib/abstract_controller.rb b/actionpack/lib/abstract_controller.rb index c1b035306b..7028cd0379 100644 --- a/actionpack/lib/abstract_controller.rb +++ b/actionpack/lib/abstract_controller.rb @@ -14,11 +14,10 @@ module AbstractController autoload :Base autoload :Callbacks autoload :Collector - autoload :Compatibility - autoload :DetailsCache autoload :Helpers autoload :Layouts autoload :Logger autoload :Rendering autoload :Translation + autoload :ViewPaths end diff --git a/actionpack/lib/abstract_controller/base.rb b/actionpack/lib/abstract_controller/base.rb index ea88a2d24d..c12b584144 100644 --- a/actionpack/lib/abstract_controller/base.rb +++ b/actionpack/lib/abstract_controller/base.rb @@ -7,7 +7,6 @@ module AbstractController class Base attr_internal :response_body attr_internal :action_name - attr_internal :formats class << self attr_reader :abstract @@ -100,11 +99,6 @@ module AbstractController abstract! - # Initialize controller with nil formats. - def initialize #:nodoc: - @_formats = nil - end - def config @config ||= ActiveSupport::InheritableOptions.new(self.class.config) end diff --git a/actionpack/lib/abstract_controller/compatibility.rb b/actionpack/lib/abstract_controller/compatibility.rb deleted file mode 100644 index 7fb93a0eb5..0000000000 --- a/actionpack/lib/abstract_controller/compatibility.rb +++ /dev/null @@ -1,18 +0,0 @@ -module AbstractController - module Compatibility - extend ActiveSupport::Concern - - def _find_layout(name, details) - 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_layout(_layout({}), {}) - nil - end - end -end diff --git a/actionpack/lib/abstract_controller/details_cache.rb b/actionpack/lib/abstract_controller/details_cache.rb deleted file mode 100644 index be1a1c0f34..0000000000 --- a/actionpack/lib/abstract_controller/details_cache.rb +++ /dev/null @@ -1,48 +0,0 @@ -module AbstractController - class HashKey - @hash_keys = Hash.new {|h,k| h[k] = {} } - - def self.get(klass, details) - @hash_keys[klass][details] ||= new(klass, details) - end - - attr_reader :hash - alias_method :eql?, :equal? - - def initialize(klass, details) - @details, @hash = details, details.hash - end - - def inspect - "#<HashKey -- details: #{@details.inspect}>" - end - end - - module DetailsCache - extend ActiveSupport::Concern - - module ClassMethods - def clear_template_caches! - ActionView::Partials::PartialRenderer::TEMPLATES.clear - template_cache.clear - super - end - - def template_cache - @template_cache ||= Hash.new {|h,k| h[k] = {} } - end - end - - def render_to_body(*args) - Thread.current[:format_locale_key] = HashKey.get(self.class, details_for_render) - super - end - - private - - def with_template_cache(name, details) - self.class.template_cache[HashKey.get(self.class, details)][name] ||= super - end - - end -end diff --git a/actionpack/lib/abstract_controller/layouts.rb b/actionpack/lib/abstract_controller/layouts.rb index beda4e633e..2f9616124a 100644 --- a/actionpack/lib/abstract_controller/layouts.rb +++ b/actionpack/lib/abstract_controller/layouts.rb @@ -170,27 +170,7 @@ module AbstractController module ClassMethods def inherited(klass) super - klass.class_eval do - _write_layout_method - @found_layouts = {} - end - end - - def clear_template_caches! - @found_layouts.clear if defined? @found_layouts - super - end - - def cache_layout(details) - layout = @found_layouts - key = Thread.current[:format_locale_key] - - # Cache nil - if layout.key?(key) - return layout[key] - else - layout[key] = yield - end + klass._write_layout_method end # This module is mixed in if layout conditions are provided. This means @@ -259,10 +239,10 @@ module AbstractController def _write_layout_method case defined?(@_layout) ? @_layout : nil when String - self.class_eval %{def _layout(details) #{@_layout.inspect} end} + self.class_eval %{def _layout; #{@_layout.inspect} end} when Symbol self.class_eval <<-ruby_eval, __FILE__, __LINE__ + 1 - def _layout(details) + def _layout #{@_layout}.tap do |layout| unless layout.is_a?(String) || !layout raise ArgumentError, "Your layout method :#{@_layout} returned \#{layout}. It " \ @@ -273,21 +253,21 @@ module AbstractController ruby_eval when Proc define_method :_layout_from_proc, &@_layout - self.class_eval %{def _layout(details) _layout_from_proc(self) end} + self.class_eval %{def _layout; _layout_from_proc(self) end} when false - self.class_eval %{def _layout(details) end} + self.class_eval %{def _layout; end} when true raise ArgumentError, "Layouts must be specified as a String, Symbol, false, or nil" when nil if name + _prefix = "layouts" unless _implied_layout_name =~ /\blayouts/ + self.class_eval <<-RUBY, __FILE__, __LINE__ + 1 - def _layout(details) - self.class.cache_layout(details) do - if template_exists?("#{_implied_layout_name}", details, :_prefix => "layouts") - "#{_implied_layout_name}" - else - super - end + def _layout + if template_exists?("#{_implied_layout_name}", #{_prefix.inspect}) + "#{_implied_layout_name}" + else + super end end RUBY @@ -297,42 +277,20 @@ module AbstractController end end - def render_to_body(options = {}) - # In the case of a partial with a layout, handle the layout - # here, and make sure the view does not try to handle it - layout = options.delete(:layout) if options.key?(:partial) - - response = super + def _normalize_options(options) + super - # This is a little bit messy. We need to explicitly handle partial - # layouts here since the core lookup logic is in the view, but - # we need to determine the layout based on the controller - # - # TODO: An easier way to handle this would probably be to override - # render_template - if layout - layout = _layout_for_option(layout, options[:_template].details) - response = layout.render(view_context, options[:locals] || {}) { response } + if _include_layout?(options) + layout = options.key?(:layout) ? options.delete(:layout) : :default + value = _layout_for_option(layout) + options[:layout] = (value =~ /\blayouts/ ? value : "layouts/#{value}") if value end - - response end private # This will be overwritten by _write_layout_method - def _layout(details) end - - # Determine the layout for a given name and details. - # - # ==== Parameters - # name<String>:: The name of the template - # details<Hash{Symbol => Object}>:: A list of details to restrict - # the lookup to. By default, layout lookup is limited to the - # formats specified for the current request. - def _layout_for_name(name, details) - name && _find_layout(name, details) - end + def _layout; end # Determine the layout for a given name and details, taking into account # the name type. @@ -342,11 +300,11 @@ module AbstractController # details<Hash{Symbol => Object}>:: A list of details to restrict # the lookup to. By default, layout lookup is limited to the # formats specified for the current request. - def _layout_for_option(name, details) + def _layout_for_option(name) case name - when String then _layout_for_name(name, details) - when true then _default_layout(details, true) - when :default then _default_layout(details, false) + when String then name + when true then _default_layout(true) + when :default then _default_layout(false) when false, nil then nil else raise ArgumentError, @@ -354,29 +312,6 @@ module AbstractController end end - def _determine_template(options) - super - - return unless (options.keys & [:text, :inline, :partial]).empty? || options.key?(:layout) - layout = options.key?(:layout) ? options[:layout] : :default - options[:_layout] = _layout_for_option(layout, options[:_template].details) - end - - # Take in the name and details and find a Template. - # - # ==== Parameters - # name<String>:: The name of the template to retrieve - # details<Hash>:: A list of details to restrict the search by. This - # might include details like the format or locale of the template. - # - # ==== Returns - # Template:: A template object matching the name and details - def _find_layout(name, details) - # TODO: Make prefix actually part of details in ViewPath#find_by_parts - prefix = details.key?(:prefix) ? details.delete(:prefix) : "layouts" - find_template(name, details, :_prefix => prefix) - end - # Returns the default layout for this controller and a given set of details. # Optionally raises an exception if the layout could not be found. # @@ -389,18 +324,24 @@ module AbstractController # # ==== Returns # Template:: The template object for the default layout (or nil) - def _default_layout(details, require_layout = false) - if require_layout && _action_has_layout? && !_layout(details) - raise ArgumentError, - "There was no default layout for #{self.class} in #{view_paths.inspect}" - end - + def _default_layout(require_layout = false) begin - _layout_for_name(_layout(details), details) if _action_has_layout? + layout_name = _layout if _action_has_layout? rescue NameError => e raise NoMethodError, "You specified #{@_layout.inspect} as the layout, but no such method was found" end + + if require_layout && _action_has_layout? && !layout_name + raise ArgumentError, + "There was no default layout for #{self.class} in #{view_paths.inspect}" + end + + layout_name + end + + def _include_layout?(options) + (options.keys & [:text, :inline, :partial]).empty? || options.key?(:layout) end def _action_has_layout? diff --git a/actionpack/lib/abstract_controller/rendering.rb b/actionpack/lib/abstract_controller/rendering.rb index 2ea4f02871..77c554fa3f 100644 --- a/actionpack/lib/abstract_controller/rendering.rb +++ b/actionpack/lib/abstract_controller/rendering.rb @@ -1,5 +1,4 @@ require "abstract_controller/base" -require "active_support/core_ext/array/wrap" module AbstractController class DoubleRenderError < Error @@ -12,28 +11,15 @@ module AbstractController module Rendering extend ActiveSupport::Concern - - included do - class_attribute :_view_paths - delegate :_view_paths, :to => :'self.class' - self._view_paths = ActionView::PathSet.new - end + include AbstractController::ViewPaths # An instance of a view class. The default view class is ActionView::Base # # The view class must have the following methods: - # View.for_controller[controller] Create a new ActionView instance for a - # controller - # View#render_partial[options] - # - responsible for setting options[:_template] - # - Returns String with the rendered partial - # options<Hash>:: see _render_partial in ActionView::Base - # View#render_template[template, layout, options, partial] - # - Returns String with the rendered template - # template<ActionView::Template>:: The template to render - # layout<ActionView::Template>:: The layout to render around the template - # options<Hash>:: See _render_template_with_layout in ActionView::Base - # partial<Boolean>:: Whether or not the template to render is a partial + # View.for_controller[controller] + # Create a new ActionView instance for a controller + # View#render_template[options] + # Returns String with the rendered template # # Override this method in a module to change the default behavior. def view_context @@ -43,57 +29,29 @@ module AbstractController # Mostly abstracts the fact that calling render twice is a DoubleRenderError. # Delegates render_to_body and sticks the result in self.response_body. def render(*args, &block) - options = _normalize_options(*args, &block) + options = _normalize_args(*args, &block) + _normalize_options(options) self.response_body = render_to_body(options) end # Raw rendering of a template to a Rack-compatible body. - # - # ==== Options - # _partial_object<Object>:: The object that is being rendered. If this - # exists, we are in the special case of rendering an object as a partial. - # # :api: plugin def render_to_body(options = {}) - # TODO: Refactor so we can just use the normal template logic for this - if options.key?(:partial) - _render_partial(options) - else - _determine_template(options) - _render_template(options) - end + _process_options(options) + _render_template(options) end # Raw rendering of a template to a string. Just convert the results of # render_to_body into a String. - # # :api: plugin - def render_to_string(*args) - options = _normalize_options(*args) + def render_to_string(options={}) + _normalize_options(options) AbstractController::Rendering.body_to_s(render_to_body(options)) end - # Renders the template from an object. - # - # ==== Options - # _template<ActionView::Template>:: The template to render - # _layout<ActionView::Template>:: The layout to wrap the template in (optional) + # Find and renders a template based on the options given. def _render_template(options) - view_context.render_template(options) - end - - # Renders the given partial. - # - # ==== Options - # partial<String|Object>:: The partial name or the object to be rendered - def _render_partial(options) - view_context.render_partial(options) - end - - # The list of view paths for this controller. See ActionView::ViewPathSet for - # more details about writing custom view paths. - def view_paths - _view_paths + view_context.render_template(options) { |template| _with_template_hook(template) } end # The prefix used in render "foo" shortcuts. @@ -115,126 +73,42 @@ module AbstractController private - # Normalize options, by converting render "foo" to render :template => "prefix/foo" - # and render "/foo" to render :file => "/foo". - def _normalize_options(action=nil, options={}) + # Normalize options by converting render "foo" to render :action => "foo" and + # render "foo/bar" to render :file => "foo/bar". + def _normalize_args(action=nil, options={}) case action + when NilClass when Hash options, action = action, nil when String, Symbol action = action.to_s - case action.index("/") - when NilClass - options[:_prefix] = _prefix - options[:_template_name] = action - when 0 - options[:file] = action - else - options[:template] = action - end + key = action.include?(?/) ? :file : :action + options[key] = action + else + options.merge!(:partial => action) end options end - # Take in a set of options and determine the template to render - # - # ==== Options - # _template<ActionView::Template>:: If this is provided, the search is over - # _template_name<#to_s>:: The name of the template to look up. Otherwise, - # use the current action name. - # _prefix<String>:: The prefix to look inside of. In a file system, this corresponds - # to a directory. - # _partial<TrueClass, FalseClass>:: Whether or not the file to look up is a partial - def _determine_template(options) - if options.key?(:text) - options[:_template] = ActionView::Template::Text.new(options[:text], format_for_text) - elsif options.key?(:inline) - handler = ActionView::Template.handler_class_for_extension(options[:type] || "erb") - template = ActionView::Template.new(options[:inline], "inline template", handler, {}) - options[:_template] = template - elsif options.key?(:template) - options[:_template_name] = options[:template] - elsif options.key?(:file) - options[:_template_name] = options[:file] + def _normalize_options(options) + if options[:partial] == true + options[:partial] = action_name end - name = (options[:_template_name] || options[:action] || action_name).to_s - options[:_prefix] ||= _prefix if (options.keys & [:partial, :file, :template]).empty? - - details = _normalize_details(options) - options[:_template] ||= with_template_cache(name, details) do - find_template(name, details, options) + if (options.keys & [:partial, :file, :template]).empty? + options[:_prefix] ||= _prefix end - end - def details_for_render - { :formats => formats, :locale => [I18n.locale] } - end - - def _normalize_details(options) - details = details_for_render - details[:formats] = Array(options[:format]) if options[:format] - details[:locale] = Array(options[:locale]) if options[:locale] - details - end - - def find_template(name, details, options) - view_paths.find(name, details, options[:_prefix], options[:_partial]) - end - - def template_exists?(name, details, options) - view_paths.exists?(name, details, options[:_prefix], options[:_partial]) - end - - def with_template_cache(name, details) - yield + options[:template] ||= (options[:action] || action_name).to_s + options end - def format_for_text - Mime[:text] + def _process_options(options) end - module ClassMethods - def clear_template_caches! - end - - # Append a path to the list of view paths for this controller. - # - # ==== Parameters - # path<String, ViewPath>:: If a String is provided, it gets converted into - # the default view path. You may also provide a custom view path - # (see ActionView::ViewPathSet for more information) - def append_view_path(path) - self.view_paths = view_paths.dup + Array.wrap(path) - end - - # Prepend a path to the list of view paths for this controller. - # - # ==== Parameters - # path<String, ViewPath>:: If a String is provided, it gets converted into - # the default view path. You may also provide a custom view path - # (see ActionView::ViewPathSet for more information) - def prepend_view_path(path) - clear_template_caches! - self.view_paths = Array.wrap(path) + view_paths.dup - end - - # A list of all of the default view paths for this controller. - def view_paths - _view_paths - end - - # Set the view paths. - # - # ==== Parameters - # paths<ViewPathSet, Object>:: If a ViewPathSet is provided, use that; - # otherwise, process the parameter into a ViewPathSet. - def view_paths=(paths) - clear_template_caches! - self._view_paths = paths.is_a?(ActionView::PathSet) ? paths : ActionView::Base.process_view_paths(paths) - _view_paths.freeze - end + def _with_template_hook(template) + self.formats = template.details[:formats] end end end diff --git a/actionpack/lib/abstract_controller/view_paths.rb b/actionpack/lib/abstract_controller/view_paths.rb new file mode 100644 index 0000000000..ec8f31cdfe --- /dev/null +++ b/actionpack/lib/abstract_controller/view_paths.rb @@ -0,0 +1,69 @@ +module AbstractController + module ViewPaths + extend ActiveSupport::Concern + + included do + class_attribute :_view_paths + self._view_paths = ActionView::PathSet.new + end + + delegate :find_template, :template_exists?, + :view_paths, :formats, :formats=, :to => :lookup_context + + # LookupContext is the object responsible to hold all information required to lookup + # templates, i.e. view paths and details. Check ActionView::LookupContext for more + # information. + def lookup_context + @lookup_context ||= ActionView::LookupContext.new(self.class._view_paths, details_for_lookup) + end + + def details_for_lookup + { } + end + + def append_view_path(path) + lookup_context.view_paths.push(*path) + end + + def prepend_view_path(path) + lookup_context.view_paths.unshift(*path) + end + + module ClassMethods + # Append a path to the list of view paths for this controller. + # + # ==== Parameters + # path<String, ViewPath>:: If a String is provided, it gets converted into + # the default view path. You may also provide a custom view path + # (see ActionView::ViewPathSet for more information) + def append_view_path(path) + self.view_paths = view_paths.dup + Array(path) + end + + # Prepend a path to the list of view paths for this controller. + # + # ==== Parameters + # path<String, ViewPath>:: If a String is provided, it gets converted into + # the default view path. You may also provide a custom view path + # (see ActionView::ViewPathSet for more information) + def prepend_view_path(path) + self.view_paths = Array(path) + view_paths.dup + end + + # A list of all of the default view paths for this controller. + def view_paths + _view_paths + end + + # Set the view paths. + # + # ==== Parameters + # paths<ViewPathSet, Object>:: If a ViewPathSet is provided, use that; + # otherwise, process the parameter into a ViewPathSet. + def view_paths=(paths) + self._view_paths = paths.is_a?(ActionView::PathSet) ? paths : ActionView::Base.process_view_paths(paths) + self._view_paths.freeze + end + end + end +end
\ No newline at end of file diff --git a/actionpack/lib/action_controller/metal/compatibility.rb b/actionpack/lib/action_controller/metal/compatibility.rb index 317a9fd951..5cad0814ca 100644 --- a/actionpack/lib/action_controller/metal/compatibility.rb +++ b/actionpack/lib/action_controller/metal/compatibility.rb @@ -2,8 +2,6 @@ module ActionController module Compatibility extend ActiveSupport::Concern - include AbstractController::Compatibility - class ::ActionController::ActionControllerError < StandardError #:nodoc: end @@ -51,14 +49,19 @@ module ActionController super end - def render_to_body(options) - if options.is_a?(Hash) && options.key?(:template) - options[:template].sub!(/^\//, '') + def _normalize_options(options) + # TODO Deprecate this. Rails 2.x allowed to give a template as action. + if options[:action] && options[:action].to_s.include?(?/) + options[:template] = options.delete(:action) end options[:text] = nil if options.delete(:nothing) == true options[:text] = " " if options.key?(:text) && options[:text].nil? + super + end + def render_to_body(options) + options[:template].sub!(/^\//, '') if options.key?(:template) super || " " end @@ -73,18 +76,5 @@ module ActionController def performed? response_body end - - # ==== Request only view path switching ==== - def append_view_path(path) - view_paths.push(*path) - end - - def prepend_view_path(path) - view_paths.unshift(*path) - end - - def view_paths - view_context.view_paths - end end end diff --git a/actionpack/lib/action_controller/metal/implicit_render.rb b/actionpack/lib/action_controller/metal/implicit_render.rb index ba2d9b686e..282dcf66b3 100644 --- a/actionpack/lib/action_controller/metal/implicit_render.rb +++ b/actionpack/lib/action_controller/metal/implicit_render.rb @@ -12,7 +12,7 @@ module ActionController def method_for_action(action_name) super || begin - if view_paths.exists?(action_name.to_s, details_for_render, controller_path) + if template_exists?(action_name.to_s, _prefix) "default_render" end end diff --git a/actionpack/lib/action_controller/metal/rendering.rb b/actionpack/lib/action_controller/metal/rendering.rb index 00a09309bf..f892bd9b91 100644 --- a/actionpack/lib/action_controller/metal/rendering.rb +++ b/actionpack/lib/action_controller/metal/rendering.rb @@ -4,44 +4,27 @@ module ActionController include ActionController::RackDelegation include AbstractController::Rendering - include AbstractController::DetailsCache - def process_action(*) - self.formats = request.formats.map {|x| x.to_sym } + def process(*) + self.formats = request.formats.map { |x| x.to_sym } super end def render(*args) raise ::AbstractController::DoubleRenderError if response_body - args << {} unless args.last.is_a?(Hash) - super(*args) - self.content_type ||= args.last[:_template].mime_type.to_s + super response_body end private - def _render_partial(options) - options[:partial] = action_name if options[:partial] == true - options[:_details] = details_for_render - super - end - - def format_for_text - formats.first + def _normalize_args(action=nil, options={}, &blk) + options = super + options[:update] = blk if block_given? + options end - def _normalize_options(action=nil, options={}, &blk) - case action - when NilClass - when Hash - options = super(action.delete(:action), action) - when String, Symbol - options = super - else - options.merge! :partial => action - end - + def _normalize_options(options) if options.key?(:text) && options[:text].respond_to?(:to_text) options[:text] = options[:text].to_text end @@ -50,17 +33,23 @@ module ActionController options[:status] = Rack::Utils.status_code(options[:status]) end - options[:update] = blk if block_given? - - _process_options(options) - options + super end def _process_options(options) status, content_type, location = options.values_at(:status, :content_type, :location) + self.status = status if status self.content_type = content_type if content_type self.headers["Location"] = url_for(location) if location + + super end + + def _with_template_hook(template) + super + self.content_type ||= template.mime_type.to_s + end + end end diff --git a/actionpack/lib/action_view.rb b/actionpack/lib/action_view.rb index 33bf0b8deb..7e9ac8720c 100644 --- a/actionpack/lib/action_view.rb +++ b/actionpack/lib/action_view.rb @@ -37,16 +37,18 @@ module ActionView autoload :Helpers autoload_under "render" do + autoload :Layouts autoload :Partials autoload :Rendering end autoload :Base - autoload :MissingTemplate, 'action_view/base' - autoload :Resolver, 'action_view/template/resolver' - autoload :PathResolver, 'action_view/template/resolver' - autoload :PathSet, 'action_view/paths' - autoload :FileSystemResolverWithFallback, 'action_view/template/resolver' + autoload :LookupContext + autoload :MissingTemplate, 'action_view/base' + autoload :Resolver, 'action_view/template/resolver' + autoload :PathResolver, 'action_view/template/resolver' + autoload :FileSystemResolver, 'action_view/template/resolver' + autoload :PathSet, 'action_view/paths' autoload :TemplateError, 'action_view/template/error' autoload :TemplateHandler, 'action_view/template' diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index e88ccc645e..38413560f3 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -173,95 +173,43 @@ module ActionView #:nodoc: module Subclasses end - include Helpers, Rendering, Partials, ::ERB::Util - - extend ActiveSupport::Memoizable + include Helpers, Rendering, Partials, Layouts, ::ERB::Util, Context + extend ActiveSupport::Memoizable ActionView.run_base_hooks(self) - attr_accessor :base_path, :assigns, :template_extension - attr_internal :captures - - def reset_formats(formats) - old_formats, self.formats = self.formats, formats - reset_hash_key - yield if block_given? - ensure - if block_given? - self.formats = old_formats - reset_hash_key - end - end - - def reset_hash_key - if defined?(AbstractController::HashKey) - # This is expensive, but we need to reset this when the format is updated, - # which currently only happens - Thread.current[:format_locale_key] = - AbstractController::HashKey.get(self.class, :formats => formats, :locale => [I18n.locale]) - end - end - - def formats - controller ? controller.formats : @formats - end - - def formats=(val) - if controller - controller.formats = val - else - @formats = val - end - end - - class << self - delegate :erb_trim_mode=, :to => 'ActionView::Template::Handlers::ERB' - delegate :logger, :to => 'ActionController::Base', :allow_nil => true - end - - @@debug_rjs = false - ## - # :singleton-method: # Specify whether RJS responses should be wrapped in a try/catch block # that alert()s the caught exception (and then re-raises it). cattr_accessor :debug_rjs + @@debug_rjs = false - # Specify whether templates should be cached. Otherwise the file we be read everytime it is accessed. - # Automatically reloading templates are not thread safe and should only be used in development mode. - @@cache_template_loading = nil - cattr_accessor :cache_template_loading - - # :nodoc: - def self.xss_safe? - true - end + class_attribute :helpers + attr_reader :helpers - def self.cache_template_loading? - ActionController::Base.allow_concurrency || (cache_template_loading.nil? ? !ActiveSupport::Dependencies.load? : cache_template_loading) + class << self + delegate :erb_trim_mode=, :to => 'ActionView::Template::Handlers::ERB' + delegate :logger, :to => 'ActionController::Base', :allow_nil => true end - attr_internal :request, :layout + attr_accessor :base_path, :assigns, :template_extension, :lookup_context + attr_internal :captures, :request, :layout, :controller, :template, :config - def controller_path - @controller_path ||= controller && controller.controller_path - end + delegate :find_template, :template_exists?, :formats, :formats=, + :view_paths, :view_paths=, :with_fallbacks, :update_details, :to => :lookup_context delegate :request_forgery_protection_token, :template, :params, :session, :cookies, :response, :headers, :flash, :action_name, :controller_name, :to => :controller delegate :logger, :to => :controller, :allow_nil => true - delegate :find, :to => :view_paths - - include Context + def self.xss_safe? #:nodoc: + true + end def self.process_view_paths(value) ActionView::PathSet.new(Array(value)) end - class_attribute :helpers - attr_reader :helpers - def self.for_controller(controller) @views ||= {} @@ -289,27 +237,26 @@ module ActionView #:nodoc: klass = self end - klass.new(controller.class.view_paths, {}, controller) + klass.new(controller.lookup_context, {}, controller) end - def initialize(view_paths = [], assigns_for_first_render = {}, controller = nil, formats = nil)#:nodoc: + def initialize(lookup_context = nil, assigns_for_first_render = {}, controller = nil, formats = nil) #:nodoc: @config = nil - @formats = formats @assigns = assigns_for_first_render.each { |key, value| instance_variable_set("@#{key}", value) } @helpers = self.class.helpers || Module.new @_controller = controller @_config = ActiveSupport::InheritableOptions.new(controller.config) if controller - @_content_for = Hash.new {|h,k| h[k] = ActiveSupport::SafeBuffer.new } + @_content_for = Hash.new { |h,k| h[k] = ActiveSupport::SafeBuffer.new } @_virtual_path = nil - self.view_paths = view_paths - end - attr_internal :controller, :template, :config - attr_reader :view_paths + @lookup_context = lookup_context.is_a?(ActionView::LookupContext) ? + lookup_context : ActionView::LookupContext.new(lookup_context) + @lookup_context.formats = formats if formats + end - def view_paths=(paths) - @view_paths = self.class.process_view_paths(paths) + def controller_path + @controller_path ||= controller && controller.controller_path end def punctuate_body!(part) diff --git a/actionpack/lib/action_view/helpers/prototype_helper.rb b/actionpack/lib/action_view/helpers/prototype_helper.rb index 67a7586699..be49b5cc28 100644 --- a/actionpack/lib/action_view/helpers/prototype_helper.rb +++ b/actionpack/lib/action_view/helpers/prototype_helper.rb @@ -182,7 +182,7 @@ module ActionView def initialize(context, &block) #:nodoc: context._evaluate_assigns_and_ivars @context, @lines = context, [] - @context.reset_formats([:js, :html]) do + @context.update_details(:formats => [:js, :html]) do include_helpers_from_context @context.with_output_buffer(@lines) do @context.instance_exec(self, &block) @@ -583,7 +583,7 @@ module ActionView end def with_formats(*args) - @context ? @context.reset_formats(args) { yield } : yield + @context ? @context.update_details(:formats => args) { yield } : yield end def javascript_object_for(object) diff --git a/actionpack/lib/action_view/lookup_context.rb b/actionpack/lib/action_view/lookup_context.rb new file mode 100644 index 0000000000..608f1ef818 --- /dev/null +++ b/actionpack/lib/action_view/lookup_context.rb @@ -0,0 +1,150 @@ +require 'active_support/core_ext/object/try' + +module ActionView + # LookupContext is the object responsible to hold all information required to lookup + # templates, i.e. view paths and details. The LookupContext is also responsible to + # generate a key, given to view paths, used in the resolver cache lookup. Since + # this key is generated just once during the request, it speeds up all cache accesses. + class LookupContext #:nodoc: + mattr_accessor :fallbacks + @@fallbacks = [FileSystemResolver.new(""), FileSystemResolver.new("/")] + + mattr_accessor :registered_details + self.registered_details = {} + + def self.register_detail(name, options = {}) + registered_details[name] = lambda do |value| + value = (value.blank? || options[:accessible] == false) ? + Array(yield) : Array(value) + value |= [nil] unless options[:allow_nil] == false + value + end + end + + register_detail(:formats) { Mime::SET.symbols } + register_detail(:locale, :accessible => false) { [I18n.locale] } + register_detail(:handlers, :accessible => false) { Template::Handlers.extensions } + + class DetailsKey #:nodoc: + attr_reader :details + alias :eql? :equal? + + @details_keys = Hash.new + + def self.get(details) + @details_keys[details] ||= new(details) + end + + def initialize(details) + @details, @hash = details, details.hash + end + + def outdated?(details) + @details != details + end + end + + def initialize(view_paths, details = {}) + self.view_paths = view_paths + self.details = details + @details_key = nil + end + + module ViewPaths + attr_reader :view_paths + + # Whenever setting view paths, makes a copy so we can manipulate then in + # instance objects as we wish. + def view_paths=(paths) + @view_paths = ActionView::Base.process_view_paths(paths) + end + + def find_template(name, prefix = nil, partial = false) + key = details_key + @view_paths.find(name, key.details, prefix, partial || false, key) + end + + def find_all(name, prefix = nil, partial = false) + key = details_key + @view_paths.find_all(name, key.details, prefix, partial || false, key) + end + + def template_exists?(name, prefix = nil, partial = false) + key = details_key + @view_paths.exists?(name, key.details, prefix, partial || false, key) + end + + # Add fallbacks to the view paths. Useful in cases you are rendering a file. + def with_fallbacks + added_resolvers = 0 + self.class.fallbacks.each do |resolver| + next if view_paths.include?(resolver) + view_paths.push(resolver) + added_resolvers += 1 + end + yield + ensure + added_resolvers.times { view_paths.pop } + end + end + + module Details + def details + @details = normalize_details(@details) + end + + def details=(new_details) + @details = new_details + details + end + + # TODO This is too expensive. Revisit this. + def details_key + latest_details = self.details + @details_key = nil if @details_key.try(:outdated?, latest_details) + @details_key ||= DetailsKey.get(latest_details) + end + + # Shortcut to read formats from details. + def formats + self.details[:formats] + end + + # Shortcut to set formats in details. + def formats=(value) + self.details = @details.merge(:formats => value) + end + + # Update the details keys by merging the given hash into the current + # details hash. If a block is given, the details are modified just during + # the execution of the block and reverted to the previous value after. + def update_details(new_details) + old_details = self.details + self.details = old_details.merge(new_details) + + if block_given? + begin + yield + ensure + self.details = old_details + end + end + end + + protected + + def normalize_details(details) + details = details.dup + # TODO: Refactor this concern out of the resolver + details.delete(:formats) if details[:formats] == [:"*/*"] + self.class.registered_details.each do |k, v| + details[k] = v.call(details[k]) + end + details + end + end + + include Details + include ViewPaths + end +end
\ No newline at end of file diff --git a/actionpack/lib/action_view/paths.rb b/actionpack/lib/action_view/paths.rb index 6e55d69d00..82a9f9a13c 100644 --- a/actionpack/lib/action_view/paths.rb +++ b/actionpack/lib/action_view/paths.rb @@ -1,46 +1,25 @@ module ActionView #:nodoc: class PathSet < Array #:nodoc: - def self.type_cast(obj, cache = nil) - # TODO: Clean this up - if obj.is_a?(String) - if cache.nil? - cache = !defined?(Rails.application) || Rails.application.config.cache_classes + %w(initialize << concat insert push unshift).each do |method| + class_eval <<-METHOD, __FILE__, __LINE__ + 1 + def #{method}(*args) + super + typecast! end - FileSystemResolverWithFallback.new(obj, :cache => cache) - else - obj - end - end - - def initialize(*args) - super(*args).map! { |obj| self.class.type_cast(obj) } - end - - def <<(obj) - super(self.class.type_cast(obj)) - end - - def concat(array) - super(array.map! { |obj| self.class.type_cast(obj) }) - end - - def insert(index, obj) - super(index, self.class.type_cast(obj)) - end - - def push(*objs) - super(*objs.map { |obj| self.class.type_cast(obj) }) + METHOD end - def unshift(*objs) - super(*objs.map { |obj| self.class.type_cast(obj) }) + def find_all(path, details = {}, prefix = nil, partial = false, key=nil) + each do |resolver| + templates = resolver.find_all(path, details, prefix, partial, key) + return templates unless templates.empty? + end + [] end - def find(path, details = {}, prefix = nil, partial = false) - template_path = path - - each do |load_path| - if template = load_path.find(template_path, details, prefix, partial) + def find(path, details = {}, prefix = nil, partial = false, key=nil) + each do |resolver| + if template = resolver.find(path, details, prefix, partial, key) return template end end @@ -48,33 +27,22 @@ module ActionView #:nodoc: raise ActionView::MissingTemplate.new(self, "#{prefix}/#{path}", details, partial) end - def exists?(path, extension = nil, prefix = nil, partial = false) - template_path = path.sub(/^\//, '') - - each do |load_path| - return true if template = load_path.find(template_path, extension, prefix, partial) - end + def exists?(path, details = {}, prefix = nil, partial = false, key=nil) + each do |resolver| + if resolver.find(path, details, prefix, partial, key) + return true + end + end false end - def find_template(original_template_path, format = nil, html_fallback = true) - return original_template_path if original_template_path.respond_to?(:render) - template_path = original_template_path.sub(/^\//, '') + protected - each do |load_path| - if template = load_path.find(template_path, format) - return template - # Try to find html version if the format is javascript - elsif format == :js && html_fallback && template = load_path["#{template_path}.#{I18n.locale}.html"] - return template - elsif format == :js && html_fallback && template = load_path["#{template_path}.html"] - return template - end + def typecast! + each_with_index do |path, i| + next unless path.is_a?(String) + self[i] = FileSystemResolver.new(path) end - - return Template.new(original_template_path, original_template_path.to_s =~ /\A\// ? "" : ".") if File.file?(original_template_path) - - raise MissingTemplate.new(self, original_template_path, format) end end end diff --git a/actionpack/lib/action_view/render/layouts.rb b/actionpack/lib/action_view/render/layouts.rb new file mode 100644 index 0000000000..91a92a833a --- /dev/null +++ b/actionpack/lib/action_view/render/layouts.rb @@ -0,0 +1,65 @@ +require 'active_support/core_ext/object/try' + +module ActionView + module Layouts + + # You can think of a layout as a method that is called with a block. _layout_for + # returns the contents that are yielded to the layout. 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_for(name = nil, &block) #:nodoc: + if !block || name + @_content_for[name || :layout] + else + capture(&block) + end + end + + # This is the method which actually finds the layout using details in the lookup + # context object. If no layout is found, it checkes if at least a layout with + # the given name exists across all details before raising the error. + def _find_layout(layout) #:nodoc: + begin + layout =~ /^\// ? + with_fallbacks { find_template(layout) } : find_template(layout) + rescue ActionView::MissingTemplate => e + update_details(:formats => nil) do + raise unless template_exists?(layout) + end + end + end + + # Contains the logic that actually renders the layout. + def _render_layout(layout, locals, &block) #:nodoc: + layout.render(self, locals){ |*name| _layout_for(*name, &block) } + end + end +end diff --git a/actionpack/lib/action_view/render/partials.rb b/actionpack/lib/action_view/render/partials.rb index 8b6dce0c1c..0fe2d560f7 100644 --- a/actionpack/lib/action_view/render/partials.rb +++ b/actionpack/lib/action_view/render/partials.rb @@ -174,17 +174,11 @@ module ActionView class PartialRenderer PARTIAL_NAMES = Hash.new {|h,k| h[k] = {} } - TEMPLATES = Hash.new {|h,k| h[k] = {} } - - attr_reader :template def initialize(view_context, options, block) @view = view_context @partial_names = PARTIAL_NAMES[@view.controller.class] - key = Thread.current[:format_locale_key] - @templates = TEMPLATES[key] if key - setup(options, block) end @@ -228,6 +222,7 @@ module ActionView if !@block && (layout = @options[:layout]) content = @view._render_layout(find_template(layout), @locals){ content } end + content end end @@ -244,9 +239,9 @@ module ActionView end def collection_with_template(template = @template) - segments, locals, as = [], @locals, @options[:as] || template.variable_name + segments, locals, as, template = [], @locals, @options[:as] || @template.variable_name, @template - counter_name = template.counter_name + counter_name = template.counter_name locals[counter_name] = -1 @collection.each do |object| @@ -256,7 +251,6 @@ module ActionView segments << template.render(@view, locals) end - @template = template segments end @@ -277,7 +271,7 @@ module ActionView end def render_partial(object = @object) - locals, view = @locals, @view + locals, view, template = @locals, @view, @template object ||= locals[template.variable_name] locals[@options[:as] || template.variable_name] = object @@ -288,6 +282,7 @@ module ActionView end private + def collection if @object.respond_to?(:to_ary) @object @@ -296,20 +291,10 @@ module ActionView end end - def find_template(path = @path) - unless @templates - path && _find_template(path) - else - path && @templates[path] ||= _find_template(path) - end - end - - def _find_template(path) - if controller = @view.controller - prefix = controller.controller_path unless path.include?(?/) - end - - @view.find(path, {:formats => @view.formats}, prefix, true) + def find_template(path=@path) + return path unless path.is_a?(String) + prefix = @view.controller_path unless path.include?(?/) + @view.find_template(path, prefix, true) end def partial_path(object = @object) @@ -324,21 +309,8 @@ module ActionView end end - def render_partial(options) - _evaluate_assigns_and_ivars - - details = options[:_details] - - # Is this needed - self.formats = details[:formats] if details - renderer = PartialRenderer.new(self, options, nil) - text = renderer.render - options[:_template] = renderer.template - text - end - def _render_partial(options, &block) #:nodoc: - if defined? @renderer + if defined?(@renderer) @renderer.setup(options, block) else @renderer = PartialRenderer.new(self, options, block) diff --git a/actionpack/lib/action_view/render/rendering.rb b/actionpack/lib/action_view/render/rendering.rb index 28b79bfcb7..0322d4b641 100644 --- a/actionpack/lib/action_view/render/rendering.rb +++ b/actionpack/lib/action_view/render/rendering.rb @@ -15,27 +15,11 @@ module ActionView def render(options = {}, locals = {}, &block) #:nodoc: case options when Hash - layout = options[:layout] - options[:locals] ||= {} - if block_given? - return safe_concat(_render_partial(options.merge(:partial => layout), &block)) - elsif options.key?(:partial) - return _render_partial(options) - end - - template = if options[:file] - find(options[:file], details_for_render) - elsif options[:inline] - handler = Template.handler_class_for_extension(options[:type] || "erb") - Template.new(options[:inline], "inline template", handler, {}) - elsif options[:text] - Template::Text.new(options[:text]) - end - - if template - layout = find(layout, details_for_render) if layout - _render_template(template, layout, :locals => options[:locals]) + content = _render_partial(options.merge(:partial => options[:layout]), &block) + safe_concat(content) + else + _render(options) end when :update update_page(&block) @@ -44,65 +28,59 @@ module ActionView end end - def details_for_render - controller.try(:details_for_render) || {:formats => formats} + # This is the API to render a ViewContext's template from a controller. + # TODO Review this name since it does not render only templates, but also + # partials, files and so forth. + def render_template(options, &block) + _evaluate_assigns_and_ivars + + # TODO Layout for partials should be handled here, because inside the + # partial renderer it looks for the layout as a partial. + if options.key?(:partial) && options[:layout] + options[:layout] = _find_layout(options[:layout]) + end + + _render(options, &block) end - # You can think of a layout as a method that is called with a block. _layout_for - # returns the contents that are yielded to the layout. 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_for(name = nil, &block) - return @_content_for[name || :layout] if !block_given? || name - capture(&block) + # This method holds the common render logic for both controllers and + # views rendering stacks. + def _render(options) #:nodoc: + if options.key?(:partial) + _render_partial(options) + else + template = _determine_template(options) + yield template if block_given? + _render_template(template, options[:layout], options) + end end - # This is the API to render a ViewContext's template from a controller. - # - # Internal Options: - # _template:: The Template object to render - # _layout:: The layout, if any, to wrap the Template in - def render_template(options) - _evaluate_assigns_and_ivars - template, layout = options.values_at(:_template, :_layout) - _render_template(template, layout, options) + # Determine the template to be rendered using the given options. + def _determine_template(options) #:nodoc: + if options.key?(:inline) + handler = Template.handler_class_for_extension(options[:type] || "erb") + Template.new(options[:inline], "inline template", handler, {}) + elsif options.key?(:text) + Template::Text.new(options[:text], self.formats.try(:first)) + elsif options.key?(:file) + with_fallbacks { find_template(options[:file], options[:_prefix]) } + elsif options.key?(:_template) + options[:_template] + elsif options.key?(:template) + find_template(options[:template], options[:_prefix]) + end end - def _render_template(template, layout = nil, options = {}) + # Renders the given template. An string representing the layout can be + # supplied as well. + def _render_template(template, layout = nil, options = {}) #:nodoc: locals = options[:locals] || {} + layout = _find_layout(layout) if layout ActiveSupport::Notifications.instrument("action_view.render_template", :identifier => template.identifier, :layout => layout.try(:identifier)) do - content = template.render(self, locals) {|*name| _layout_for(*name) } + content = template.render(self, locals) { |*name| _layout_for(*name) } @_content_for[:layout] = content if layout @@ -114,8 +92,5 @@ module ActionView end end - def _render_layout(layout, locals, &block) - layout.render(self, locals){ |*name| _layout_for(*name, &block) } - end end end diff --git a/actionpack/lib/action_view/template/resolver.rb b/actionpack/lib/action_view/template/resolver.rb index 8c81914aac..9a011f7638 100644 --- a/actionpack/lib/action_view/template/resolver.rb +++ b/actionpack/lib/action_view/template/resolver.rb @@ -4,45 +4,31 @@ require "active_support/core_ext/array/wrap" require "action_view/template" module ActionView - # Abstract superclass class Resolver - - class_inheritable_accessor(:registered_details) - self.registered_details = {} - - def self.register_detail(name, options = {}) - registered_details[name] = lambda do |val| - val = Array.wrap(val || yield) - val |= [nil] unless options[:allow_nil] == false - val - end - end - - register_detail(:locale) { [I18n.locale] } - register_detail(:formats) { Mime::SET.symbols } - register_detail(:handlers) { Template::Handlers.extensions } - - def initialize(options = {}) - @cache = options[:cache] - @cached = {} + def initialize + @cached = Hash.new { |h1,k1| h1[k1] = + Hash.new { |h2,k2| h2[k2] = Hash.new { |h3, k3| h3[k3] = {} } } } end def find(*args) find_all(*args).first end - # Normalizes the arguments and passes it on to find_template - def find_all(name, details = {}, prefix = nil, partial = nil) - details = normalize_details(details) + # Normalizes the arguments and passes it on to find_template. + def find_all(name, details = {}, prefix = nil, partial = nil, key=nil) name, prefix = normalize_name(name, prefix) - cached([name, details, prefix, partial]) do + cached(key, prefix, name, partial) do find_templates(name, details, prefix, partial) end end private + def caching? + @caching ||= !defined?(Rails.application) || Rails.application.config.cache_classes + end + # This is what child classes implement. No defaults are needed # because Resolver guarantees that the arguments are present and # normalized. @@ -50,16 +36,6 @@ module ActionView raise NotImplementedError end - def normalize_details(details) - details = details.dup - # TODO: Refactor this concern out of the resolver - details.delete(:formats) if details[:formats] == [:"*/*"] - registered_details.each do |k, v| - details[k] = v.call(details[k]) - end - details - end - # Support legacy foo.erb names even though we now ignore .erb # as well as incorrectly putting part of the path in the template # name instead of the prefix. @@ -71,29 +47,32 @@ module ActionView return parts.pop, [prefix, *parts].compact.join("/") end - def cached(key) - return yield unless @cache - return @cached[key] if @cached.key?(key) - @cached[key] = yield + def cached(key, prefix, name, partial) + return yield unless key && caching? + scope = @cached[key][prefix][name] + if scope.key?(partial) + scope[partial] + else + scope[partial] = yield + end end end class PathResolver < Resolver - EXTENSION_ORDER = [:locale, :formats, :handlers] def to_s @path.to_s end - alias to_path to_s + alias :to_path :to_s + + private def find_templates(name, details, prefix, partial) path = build_path(name, details, prefix, partial) query(path, EXTENSION_ORDER.map { |ext| details[ext] }) end - private - def build_path(name, details, prefix, partial) path = "" path << "#{prefix}/" unless prefix.empty? @@ -133,30 +112,15 @@ module ActionView end class FileSystemResolver < PathResolver - def initialize(path, options = {}) + def initialize(path) raise ArgumentError, "path already is a Resolver class" if path.is_a?(Resolver) - super(options) + super() @path = Pathname.new(path).expand_path end - end - - # TODO: remove hack - class FileSystemResolverWithFallback < Resolver - def initialize(path, options = {}) - super(options) - @paths = [FileSystemResolver.new(path, options), FileSystemResolver.new("", options), FileSystemResolver.new("/", options)] - end - - def find_templates(*args) - @paths.each do |p| - template = p.find_templates(*args) - return template unless template.empty? - end - [] - end - def to_s - @paths.first.to_s + def eql?(resolver) + self.class.equal?(resolver.class) && to_path == resolver.to_path end + alias :== :eql? end end diff --git a/actionpack/lib/action_view/template/text.rb b/actionpack/lib/action_view/template/text.rb index 2abb352d4e..5978a8a3ac 100644 --- a/actionpack/lib/action_view/template/text.rb +++ b/actionpack/lib/action_view/template/text.rb @@ -1,11 +1,10 @@ module ActionView #:nodoc: class Template class Text < String #:nodoc: - HTML = Mime[:html] - - def initialize(string, content_type = HTML) + def initialize(string, content_type = nil) super(string.to_s) - @content_type = Mime[content_type] || content_type + @content_type = Mime[content_type] || content_type if content_type + @content_type ||= Mime::TEXT end def details diff --git a/actionpack/test/abstract/abstract_controller_test.rb b/actionpack/test/abstract/abstract_controller_test.rb index 4ad87d9762..f70d497481 100644 --- a/actionpack/test/abstract/abstract_controller_test.rb +++ b/actionpack/test/abstract/abstract_controller_test.rb @@ -59,11 +59,11 @@ module AbstractController end def rendering_to_body - self.response_body = render_to_body :_template_name => "naked_render.erb" + self.response_body = render_to_body :template => "naked_render.erb" end def rendering_to_string - self.response_body = render_to_string :_template_name => "naked_render.erb" + self.response_body = render_to_string :template => "naked_render.erb" end end diff --git a/actionpack/test/abstract/details_cache_test.rb b/actionpack/test/abstract/details_cache_test.rb deleted file mode 100644 index ee746c1bb0..0000000000 --- a/actionpack/test/abstract/details_cache_test.rb +++ /dev/null @@ -1,57 +0,0 @@ -require 'abstract_unit' - -module AbstractController - module Testing - - class CachedController < AbstractController::Base - include AbstractController::Rendering - include AbstractController::DetailsCache - - self.view_paths = [ActionView::FixtureResolver.new( - "default.erb" => "With Default", - "template.erb" => "With Template", - "some/file.erb" => "With File", - "template_name.erb" => "With Template Name" - )] - end - - class TestLocalizedCache < ActiveSupport::TestCase - - def setup - @controller = CachedController.new - CachedController.clear_template_caches! - end - - def test_templates_are_cached - @controller.render :template => "default.erb" - assert_equal "With Default", @controller.response_body - - cached = @controller.class.template_cache - assert_equal 1, cached.size - assert_kind_of ActionView::Template, cached.values.first["default.erb"] - end - - def test_cache_is_used - CachedController.new.render :template => "default.erb" - - @controller.expects(:find_template).never - @controller.render :template => "default.erb" - - assert_equal 1, @controller.class.template_cache.size - end - - def test_cache_changes_with_locale - CachedController.new.render :template => "default.erb" - - I18n.locale = :es - @controller.render :template => "default.erb" - - assert_equal 2, @controller.class.template_cache.size - ensure - I18n.locale = :en - end - - end - - end -end diff --git a/actionpack/test/abstract/layouts_test.rb b/actionpack/test/abstract/layouts_test.rb index b6d89ea489..65a50807fd 100644 --- a/actionpack/test/abstract/layouts_test.rb +++ b/actionpack/test/abstract/layouts_test.rb @@ -8,41 +8,52 @@ module AbstractControllerTests include AbstractController::Rendering include AbstractController::Layouts + def _prefix + "template" + end + self.view_paths = [ActionView::FixtureResolver.new( - "layouts/hello.erb" => "With String <%= yield %>", - "layouts/hello_override.erb" => "With Override <%= yield %>", - "layouts/abstract_controller_tests/layouts/with_string_implied_child.erb" => - "With Implied <%= yield %>", - "layouts/overwrite.erb" => "Overwrite <%= yield %>", - "layouts/with_false_layout.erb" => "False Layout <%= yield %>" + "abstract_controller_tests/layouts/with_string_implied_child.erb" => + "With Implied <%= yield %>", + "layouts/hello.erb" => "With String <%= yield %>", + "layouts/hello_override.erb" => "With Override <%= yield %>", + "layouts/overwrite.erb" => "Overwrite <%= yield %>", + "layouts/with_false_layout.erb" => "False Layout <%= yield %>" )] end class Blank < Base - self.view_paths = [] - + self.view_paths = ActionView::FixtureResolver.new("template/index.erb" => "Hello blank!") + def index - render :_template => ActionView::Template::Text.new("Hello blank!") + render end end class WithString < Base layout "hello" - + + append_view_path ActionView::FixtureResolver.new( + "template/index.erb" => "Hello string!", + "template/overwrite_default.erb" => "Hello string!", + "template/overwrite_false.erb" => "Hello string!", + "template/overwrite_string.erb" => "Hello string!" + ) + def index - render :_template => ActionView::Template::Text.new("Hello string!") + render end def overwrite_default - render :_template => ActionView::Template::Text.new("Hello string!"), :layout => :default + render :layout => :default end def overwrite_false - render :_template => ActionView::Template::Text.new("Hello string!"), :layout => false + render :layout => false end def overwrite_string - render :_template => ActionView::Template::Text.new("Hello string!"), :layout => "overwrite" + render :layout => "overwrite" end def overwrite_skip @@ -70,18 +81,28 @@ module AbstractControllerTests class WithProc < Base layout proc { |c| "overwrite" } + append_view_path ActionView::FixtureResolver.new( + "template/index.erb" => "Hello proc!" + ) + def index - render :_template => ActionView::Template::Text.new("Hello proc!") + render end end class WithSymbol < Base layout :hello - + + append_view_path ActionView::FixtureResolver.new( + "template/index.erb" => "Hello symbol!" + ) + def index - render :_template => ActionView::Template::Text.new("Hello symbol!") + render end - private + + private + def hello "overwrite" end @@ -89,11 +110,17 @@ module AbstractControllerTests class WithSymbolReturningString < Base layout :no_hello - + + append_view_path ActionView::FixtureResolver.new( + "template/index.erb" => "Hello missing symbol!" + ) + def index - render :_template => ActionView::Template::Text.new("Hello missing symbol!") + render end - private + + private + def no_hello nil end @@ -101,19 +128,28 @@ module AbstractControllerTests class WithSymbolReturningNil < Base layout :nilz - + + append_view_path ActionView::FixtureResolver.new( + "template/index.erb" => "Hello nilz!" + ) + def index - render :_template => ActionView::Template::Text.new("Hello nilz!") + render end - def nilz() end + def nilz + end end class WithSymbolReturningObj < Base layout :objekt - + + append_view_path ActionView::FixtureResolver.new( + "template/index.erb" => "Hello object!" + ) + def index - render :_template => ActionView::Template::Text.new("Hello nilz!") + render end def objekt @@ -123,33 +159,49 @@ module AbstractControllerTests class WithSymbolAndNoMethod < Base layout :no_method - + + append_view_path ActionView::FixtureResolver.new( + "template/index.erb" => "Hello boom!" + ) + def index - render :_template => ActionView::Template::Text.new("Hello boom!") + render end end class WithMissingLayout < Base layout "missing" - + + append_view_path ActionView::FixtureResolver.new( + "template/index.erb" => "Hello missing!" + ) + def index - render :_template => ActionView::Template::Text.new("Hello missing!") + render end end class WithFalseLayout < Base layout false - + + append_view_path ActionView::FixtureResolver.new( + "template/index.erb" => "Hello false!" + ) + def index - render :_template => ActionView::Template::Text.new("Hello false!") + render end end class WithNilLayout < Base layout nil + + append_view_path ActionView::FixtureResolver.new( + "template/index.erb" => "Hello nil!" + ) def index - render :_template => ActionView::Template::Text.new("Hello nil!") + render end end diff --git a/actionpack/test/abstract/render_test.rb b/actionpack/test/abstract/render_test.rb index db924633ca..25dc8bd804 100644 --- a/actionpack/test/abstract/render_test.rb +++ b/actionpack/test/abstract/render_test.rb @@ -15,13 +15,8 @@ module AbstractController "renderer/default.erb" => "With Default", "renderer/string.erb" => "With String", "renderer/symbol.erb" => "With Symbol", - "renderer/template_name.erb" => "With Template Name", "string/with_path.erb" => "With String With Path", - "some/file.erb" => "With File", - "with_format.html.erb" => "With html format", - "with_format.xml.erb" => "With xml format", - "with_locale.en.erb" => "With en locale", - "with_locale.pl.erb" => "With pl locale" + "some/file.erb" => "With File" )] def template @@ -55,30 +50,6 @@ module AbstractController def symbol render :symbol end - - def template_name - render :_template_name => :template_name - end - - def object - render :_template => ActionView::Template::Text.new("With Object") - end - - def with_html_format - render :template => "with_format", :format => :html - end - - def with_xml_format - render :template => "with_format", :format => :xml - end - - def with_en_locale - render :template => "with_locale" - end - - def with_pl_locale - render :template => "with_locale", :locale => :pl - end end class TestRenderer < ActiveSupport::TestCase @@ -126,36 +97,6 @@ module AbstractController @controller.process(:string_with_path) assert_equal "With String With Path", @controller.response_body end - - def test_render_template_name - @controller.process(:template_name) - assert_equal "With Template Name", @controller.response_body - end - - def test_render_object - @controller.process(:object) - assert_equal "With Object", @controller.response_body - end - - def test_render_with_html_format - @controller.process(:with_html_format) - assert_equal "With html format", @controller.response_body - end - - def test_render_with_xml_format - @controller.process(:with_xml_format) - assert_equal "With xml format", @controller.response_body - end - - def test_render_with_en_locale - @controller.process(:with_en_locale) - assert_equal "With en locale", @controller.response_body - end - - def test_render_with_pl_locale - @controller.process(:with_pl_locale) - assert_equal "With pl locale", @controller.response_body - end end end end diff --git a/actionpack/test/lib/fixture_template.rb b/actionpack/test/lib/fixture_template.rb index 6b9e7c5270..a7f0490984 100644 --- a/actionpack/test/lib/fixture_template.rb +++ b/actionpack/test/lib/fixture_template.rb @@ -1,7 +1,7 @@ module ActionView #:nodoc: class FixtureResolver < PathResolver - def initialize(hash = {}, options = {}) - super(options) + def initialize(hash = {}) + super() @hash = hash end diff --git a/actionpack/test/template/compiled_templates_test.rb b/actionpack/test/template/compiled_templates_test.rb index 632988bb2e..0a3409064f 100644 --- a/actionpack/test/template/compiled_templates_test.rb +++ b/actionpack/test/template/compiled_templates_test.rb @@ -44,7 +44,7 @@ class CompiledTemplatesTest < Test::Unit::TestCase end def render_without_cache(*args) - path = ActionView::FileSystemResolverWithFallback.new(FIXTURE_LOAD_PATH) + path = ActionView::FileSystemResolver.new(FIXTURE_LOAD_PATH) view_paths = ActionView::Base.process_view_paths(path) ActionView::Base.new(view_paths, {}).render(*args) end diff --git a/actionpack/test/template/javascript_helper_test.rb b/actionpack/test/template/javascript_helper_test.rb index 368a9c2514..6604f1c095 100644 --- a/actionpack/test/template/javascript_helper_test.rb +++ b/actionpack/test/template/javascript_helper_test.rb @@ -7,8 +7,8 @@ class JavaScriptHelperTest < ActionView::TestCase attr_accessor :formats, :output_buffer - def reset_formats(format) - @format = format + def update_details(details) + @details = details yield if block_given? end diff --git a/actionpack/test/template/prototype_helper_test.rb b/actionpack/test/template/prototype_helper_test.rb index 6811d3aaf3..619293dc43 100644 --- a/actionpack/test/template/prototype_helper_test.rb +++ b/actionpack/test/template/prototype_helper_test.rb @@ -39,8 +39,8 @@ class Author::Nested < Author; end class PrototypeHelperBaseTest < ActionView::TestCase attr_accessor :formats, :output_buffer - def reset_formats(format) - @format = format + def update_details(details) + @details = details yield if block_given? end diff --git a/actionpack/test/template/render_test.rb b/actionpack/test/template/render_test.rb index 6dbadc9304..37a3975a54 100644 --- a/actionpack/test/template/render_test.rb +++ b/actionpack/test/template/render_test.rb @@ -270,7 +270,7 @@ class CachedViewRenderTest < ActiveSupport::TestCase # Ensure view path cache is primed def setup view_paths = ActionController::Base.view_paths - assert_equal ActionView::FileSystemResolverWithFallback, view_paths.first.class + assert_equal ActionView::FileSystemResolver, view_paths.first.class setup_view(view_paths) end end @@ -281,9 +281,9 @@ class LazyViewRenderTest < ActiveSupport::TestCase # Test the same thing as above, but make sure the view path # is not eager loaded def setup - path = ActionView::FileSystemResolverWithFallback.new(FIXTURE_LOAD_PATH) + path = ActionView::FileSystemResolver.new(FIXTURE_LOAD_PATH) view_paths = ActionView::Base.process_view_paths(path) - assert_equal ActionView::FileSystemResolverWithFallback, view_paths.first.class + assert_equal ActionView::FileSystemResolver.new(FIXTURE_LOAD_PATH), view_paths.first setup_view(view_paths) end end |