diff options
Diffstat (limited to 'actionpack')
30 files changed, 229 insertions, 247 deletions
diff --git a/actionpack/lib/abstract_controller.rb b/actionpack/lib/abstract_controller.rb index 2da4dc052c..de95f935c2 100644 --- a/actionpack/lib/abstract_controller.rb +++ b/actionpack/lib/abstract_controller.rb @@ -12,6 +12,7 @@ require 'active_support/i18n' module AbstractController extend ActiveSupport::Autoload + autoload :Assigns autoload :Base autoload :Callbacks autoload :Collector diff --git a/actionpack/lib/abstract_controller/assigns.rb b/actionpack/lib/abstract_controller/assigns.rb new file mode 100644 index 0000000000..21459c6d51 --- /dev/null +++ b/actionpack/lib/abstract_controller/assigns.rb @@ -0,0 +1,21 @@ +module AbstractController + module Assigns + # This method should return a hash with assigns. + # You can overwrite this configuration per controller. + # :api: public + def view_assigns + hash = {} + variables = instance_variable_names + variables -= protected_instance_variables if respond_to?(:protected_instance_variables) + variables.each { |name| hash[name] = instance_variable_get(name) } + hash + end + + # This method assigns the hash specified in _assigns_hash to the given object. + # :api: private + # TODO Ideally, this should be done on AV::Base.new initialization. + def _evaluate_assigns(object) + view_assigns.each { |k,v| object.instance_variable_set(k, v) } + end + end +end
\ No newline at end of file diff --git a/actionpack/lib/abstract_controller/layouts.rb b/actionpack/lib/abstract_controller/layouts.rb index 2f9616124a..95a6101109 100644 --- a/actionpack/lib/abstract_controller/layouts.rb +++ b/actionpack/lib/abstract_controller/layouts.rb @@ -284,6 +284,12 @@ module AbstractController layout = options.key?(:layout) ? options.delete(:layout) : :default value = _layout_for_option(layout) options[:layout] = (value =~ /\blayouts/ ? value : "layouts/#{value}") if value + + # 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] = view_context.find_layout(options[:layout]) + end end end diff --git a/actionpack/lib/abstract_controller/rendering.rb b/actionpack/lib/abstract_controller/rendering.rb index 42f4939108..16664098e5 100644 --- a/actionpack/lib/abstract_controller/rendering.rb +++ b/actionpack/lib/abstract_controller/rendering.rb @@ -31,6 +31,8 @@ module AbstractController module Rendering extend ActiveSupport::Concern + + include AbstractController::Assigns include AbstractController::ViewPaths # Overwrite process to setup I18n proxy. @@ -54,8 +56,8 @@ module AbstractController @_view_context ||= ActionView::Base.for_controller(self) end - # Mostly abstracts the fact that calling render twice is a DoubleRenderError. - # Delegates render_to_body and sticks the result in self.response_body. + # Normalize arguments, options and then delegates render_to_body and + # sticks the result in self.response_body. def render(*args, &block) options = _normalize_args(*args, &block) _normalize_options(options) @@ -78,8 +80,10 @@ module AbstractController end # Find and renders a template based on the options given. - def _render_template(options) - view_context.render_template(options) { |template| _with_template_hook(template) } + # :api: private + def _render_template(options) #:nodoc: + _evaluate_assigns(view_context) + view_context.render(options) end # The prefix used in render "foo" shortcuts. @@ -134,9 +138,5 @@ module AbstractController def _process_options(options) end - - def _with_template_hook(template) - self.formats = template.formats - end end end diff --git a/actionpack/lib/abstract_controller/view_paths.rb b/actionpack/lib/abstract_controller/view_paths.rb index c2a9f6336d..b331eb51b6 100644 --- a/actionpack/lib/abstract_controller/view_paths.rb +++ b/actionpack/lib/abstract_controller/view_paths.rb @@ -7,7 +7,7 @@ module AbstractController self._view_paths = ActionView::PathSet.new end - delegate :template_exists?, :view_paths, :formats, :formats=, + delegate :find_template, :template_exists?, :view_paths, :formats, :formats=, :locale, :locale=, :to => :lookup_context # LookupContext is the object responsible to hold all information required to lookup @@ -29,10 +29,6 @@ module AbstractController lookup_context.view_paths.unshift(*path) end - def template_exists?(*args) - lookup_context.exists?(*args) - end - module ClassMethods # Append a path to the list of view paths for this controller. # diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index fcd3cb9bd3..ad2b68af21 100644 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -2,7 +2,6 @@ module ActionController class Base < Metal abstract! - include AbstractController::Callbacks include AbstractController::Layouts include AbstractController::Translation @@ -23,6 +22,7 @@ module ActionController # Rails 2.x compatibility include ActionController::Compatibility + include ActionController::ImplicitRender include ActionController::Cookies include ActionController::Flash @@ -36,8 +36,12 @@ module ActionController # Add instrumentations hooks at the bottom, to ensure they instrument # all the methods properly. include ActionController::Instrumentation - include ImplicitRender + # Before callbacks should also be executed the earliest as possible, so + # also include them at the bottom. + include AbstractController::Callbacks + + # The same with rescue, append it at the end to wrap as much as possible. include ActionController::Rescue def self.inherited(klass) diff --git a/actionpack/lib/action_controller/caching/fragments.rb b/actionpack/lib/action_controller/caching/fragments.rb index bb5ff95a67..89787727bd 100644 --- a/actionpack/lib/action_controller/caching/fragments.rb +++ b/actionpack/lib/action_controller/caching/fragments.rb @@ -41,9 +41,7 @@ module ActionController #:nodoc: else pos = buffer.length block.call - content = buffer[pos..-1] - content = content.as_str if content.respond_to?(:as_str) - write_fragment(name, content, options) + write_fragment(name, buffer[pos..-1], options) end else block.call @@ -53,9 +51,10 @@ module ActionController #:nodoc: # Writes <tt>content</tt> to the location signified by <tt>key</tt> (see <tt>expire_fragment</tt> for acceptable formats) def write_fragment(key, content, options = nil) return content unless cache_configured? - key = fragment_cache_key(key) + key = fragment_cache_key(key) instrument_fragment_cache :write_fragment, key do + content = content.html_safe.to_str if content.respond_to?(:html_safe) cache_store.write(key, content, options) end content @@ -64,10 +63,11 @@ module ActionController #:nodoc: # Reads a cached fragment from the location signified by <tt>key</tt> (see <tt>expire_fragment</tt> for acceptable formats) def read_fragment(key, options = nil) return unless cache_configured? - key = fragment_cache_key(key) + key = fragment_cache_key(key) instrument_fragment_cache :read_fragment, key do - cache_store.read(key, options) + result = cache_store.read(key, options) + result.respond_to?(:html_safe) ? result.html_safe : result end end diff --git a/actionpack/lib/action_controller/metal/mime_responds.rb b/actionpack/lib/action_controller/metal/mime_responds.rb index e70a20b2be..2ac199265d 100644 --- a/actionpack/lib/action_controller/metal/mime_responds.rb +++ b/actionpack/lib/action_controller/metal/mime_responds.rb @@ -261,6 +261,7 @@ module ActionController #:nodoc: block.call(collector) if block_given? if format = request.negotiate_mime(collector.order) + self.content_type ||= format.to_s self.formats = [format.to_sym] collector.response_for(format) else diff --git a/actionpack/lib/action_controller/metal/renderers.rb b/actionpack/lib/action_controller/metal/renderers.rb index 49d3d6b466..08325b468c 100644 --- a/actionpack/lib/action_controller/metal/renderers.rb +++ b/actionpack/lib/action_controller/metal/renderers.rb @@ -87,8 +87,9 @@ module ActionController end add :update do |proc, options| + _evaluate_assigns(view_context) generator = ActionView::Helpers::PrototypeHelper::JavaScriptGenerator.new(view_context, &proc) - self.content_type = Mime::JS + self.content_type = Mime::JS self.response_body = generator.to_s end end diff --git a/actionpack/lib/action_controller/metal/rendering.rb b/actionpack/lib/action_controller/metal/rendering.rb index f892bd9b91..86bb810947 100644 --- a/actionpack/lib/action_controller/metal/rendering.rb +++ b/actionpack/lib/action_controller/metal/rendering.rb @@ -5,26 +5,31 @@ module ActionController include ActionController::RackDelegation include AbstractController::Rendering - def process(*) + # Before processing, set the request formats in current controller formats. + def process_action(*) #:nodoc: self.formats = request.formats.map { |x| x.to_sym } super end - def render(*args) + # Check for double render errors and set the content_type after rendering. + def render(*args) #:nodoc: raise ::AbstractController::DoubleRenderError if response_body super + self.content_type ||= Mime[formats.first].to_s response_body end private - def _normalize_args(action=nil, options={}, &blk) + # Normalize arguments by catching blocks and setting them on :update. + def _normalize_args(action=nil, options={}, &blk) #:nodoc: options = super options[:update] = blk if block_given? options end - def _normalize_options(options) + # Normalize both text and status options. + def _normalize_options(options) #:nodoc: if options.key?(:text) && options[:text].respond_to?(:to_text) options[:text] = options[:text].to_text end @@ -36,7 +41,8 @@ module ActionController super end - def _process_options(options) + # Process controller specific options, as status, content-type and location. + def _process_options(options) #:nodoc: status, content_type, location = options.values_at(:status, :content_type, :location) self.status = status if status @@ -46,10 +52,5 @@ module ActionController 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_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 0b7b09ee7a..f9b27a5a03 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -362,11 +362,11 @@ module ActionDispatch attr_reader :plural, :singular, :options def initialize(entities, options = {}) - entities = entities.to_s + @name = entities.to_s @options = options - @plural = entities.pluralize - @singular = entities.singularize + @plural = @name.pluralize + @singular = @name.singularize end def default_actions @@ -393,7 +393,7 @@ module ActionDispatch end def name - options[:as] || plural + options[:as] || @name end def controller @@ -438,8 +438,8 @@ module ActionDispatch end end - def name - options[:as] || singular + def member_name + name end end @@ -468,8 +468,8 @@ module ActionDispatch post :create if resource.actions.include?(:create) put :update if resource.actions.include?(:update) delete :destroy if resource.actions.include?(:destroy) - get :new, :as => resource.singular if resource.actions.include?(:new) - get :edit, :as => resource.singular if resource.actions.include?(:edit) + get :new, :as => resource.name if resource.actions.include?(:new) + get :edit, :as => resource.name if resource.actions.include?(:edit) end end diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index ffe3060404..feaf45c333 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -194,7 +194,7 @@ module ActionView #:nodoc: attr_accessor :base_path, :assigns, :template_extension, :lookup_context attr_internal :captures, :request, :layout, :controller, :template, :config - delegate :find, :exists?, :formats, :formats=, :locale, :locale=, + delegate :find_template, :template_exists?, :formats, :formats=, :locale, :locale=, :view_paths, :view_paths=, :with_fallbacks, :update_details, :to => :lookup_context delegate :request_forgery_protection_token, :template, :params, :session, :cookies, :response, :headers, @@ -264,14 +264,5 @@ module ActionView #:nodoc: response.body_parts << part nil end - - # Evaluates the local assigns and controller ivars, pushes them to the view. - def _evaluate_assigns_and_ivars #: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 - end end end diff --git a/actionpack/lib/action_view/helpers/active_model_helper.rb b/actionpack/lib/action_view/helpers/active_model_helper.rb index 4e12cdab54..e3db2923f7 100644 --- a/actionpack/lib/action_view/helpers/active_model_helper.rb +++ b/actionpack/lib/action_view/helpers/active_model_helper.rb @@ -129,7 +129,7 @@ module ActionView if (obj = (object.respond_to?(:errors) ? object : instance_variable_get("@#{object}"))) && (errors = obj.errors[method]) content_tag("div", - (options[:prepend_text].html_safe << errors.first).safe_concat(options[:append_text]), + "#{options[:prepend_text]}#{ERB::Util.h(errors.first)}#{options[:append_text]}".html_safe, :class => options[:css_class] ) else diff --git a/actionpack/lib/action_view/helpers/asset_tag_helper.rb b/actionpack/lib/action_view/helpers/asset_tag_helper.rb index 0c488b6793..03ae8ce0d8 100644 --- a/actionpack/lib/action_view/helpers/asset_tag_helper.rb +++ b/actionpack/lib/action_view/helpers/asset_tag_helper.rb @@ -242,12 +242,12 @@ module ActionView # == Caching multiple javascripts into one # # You can also cache multiple javascripts into one file, which requires less HTTP connections to download and can better be - # compressed by gzip (leading to faster transfers). Caching will only happen if ActionController::Base.perform_caching + # compressed by gzip (leading to faster transfers). Caching will only happen if config.perform_caching # is set to <tt>true</tt> (which is the case by default for the Rails production environment, but not for the development # environment). # # ==== Examples - # javascript_include_tag :all, :cache => true # when ActionController::Base.perform_caching is false => + # javascript_include_tag :all, :cache => true # when config.perform_caching is false => # <script type="text/javascript" src="/javascripts/prototype.js"></script> # <script type="text/javascript" src="/javascripts/effects.js"></script> # ... @@ -255,15 +255,15 @@ module ActionView # <script type="text/javascript" src="/javascripts/shop.js"></script> # <script type="text/javascript" src="/javascripts/checkout.js"></script> # - # javascript_include_tag :all, :cache => true # when ActionController::Base.perform_caching is true => + # javascript_include_tag :all, :cache => true # when config.perform_caching is true => # <script type="text/javascript" src="/javascripts/all.js"></script> # - # javascript_include_tag "prototype", "cart", "checkout", :cache => "shop" # when ActionController::Base.perform_caching is false => + # javascript_include_tag "prototype", "cart", "checkout", :cache => "shop" # when config.perform_caching is false => # <script type="text/javascript" src="/javascripts/prototype.js"></script> # <script type="text/javascript" src="/javascripts/cart.js"></script> # <script type="text/javascript" src="/javascripts/checkout.js"></script> # - # javascript_include_tag "prototype", "cart", "checkout", :cache => "shop" # when ActionController::Base.perform_caching is true => + # javascript_include_tag "prototype", "cart", "checkout", :cache => "shop" # when config.perform_caching is true => # <script type="text/javascript" src="/javascripts/shop.js"></script> # # The <tt>:recursive</tt> option is also available for caching: @@ -275,11 +275,11 @@ module ActionView cache = concat || options.delete("cache") recursive = options.delete("recursive") - if concat || (ActionController::Base.perform_caching && cache) + if concat || (config.perform_caching && cache) joined_javascript_name = (cache == true ? "all" : cache) + ".js" joined_javascript_path = File.join(joined_javascript_name[/^#{File::SEPARATOR}/] ? config.assets_dir : config.javascripts_dir, joined_javascript_name) - unless ActionController::Base.perform_caching && File.exists?(joined_javascript_path) + unless config.perform_caching && File.exists?(joined_javascript_path) write_asset_file_contents(joined_javascript_path, compute_javascript_paths(sources, recursive)) end javascript_src_tag(joined_javascript_name, options) @@ -390,25 +390,25 @@ module ActionView # == Caching multiple stylesheets into one # # You can also cache multiple stylesheets into one file, which requires less HTTP connections and can better be - # compressed by gzip (leading to faster transfers). Caching will only happen if ActionController::Base.perform_caching + # compressed by gzip (leading to faster transfers). Caching will only happen if config.perform_caching # is set to true (which is the case by default for the Rails production environment, but not for the development # environment). Examples: # # ==== Examples - # stylesheet_link_tag :all, :cache => true # when ActionController::Base.perform_caching is false => + # stylesheet_link_tag :all, :cache => true # when config.perform_caching is false => # <link href="/stylesheets/style1.css" media="screen" rel="stylesheet" type="text/css" /> # <link href="/stylesheets/styleB.css" media="screen" rel="stylesheet" type="text/css" /> # <link href="/stylesheets/styleX2.css" media="screen" rel="stylesheet" type="text/css" /> # - # stylesheet_link_tag :all, :cache => true # when ActionController::Base.perform_caching is true => + # stylesheet_link_tag :all, :cache => true # when config.perform_caching is true => # <link href="/stylesheets/all.css" media="screen" rel="stylesheet" type="text/css" /> # - # stylesheet_link_tag "shop", "cart", "checkout", :cache => "payment" # when ActionController::Base.perform_caching is false => + # stylesheet_link_tag "shop", "cart", "checkout", :cache => "payment" # when config.perform_caching is false => # <link href="/stylesheets/shop.css" media="screen" rel="stylesheet" type="text/css" /> # <link href="/stylesheets/cart.css" media="screen" rel="stylesheet" type="text/css" /> # <link href="/stylesheets/checkout.css" media="screen" rel="stylesheet" type="text/css" /> # - # stylesheet_link_tag "shop", "cart", "checkout", :cache => "payment" # when ActionController::Base.perform_caching is true => + # stylesheet_link_tag "shop", "cart", "checkout", :cache => "payment" # when config.perform_caching is true => # <link href="/stylesheets/payment.css" media="screen" rel="stylesheet" type="text/css" /> # # The <tt>:recursive</tt> option is also available for caching: @@ -426,11 +426,11 @@ module ActionView cache = concat || options.delete("cache") recursive = options.delete("recursive") - if concat || (ActionController::Base.perform_caching && cache) + if concat || (config.perform_caching && cache) joined_stylesheet_name = (cache == true ? "all" : cache) + ".css" joined_stylesheet_path = File.join(joined_stylesheet_name[/^#{File::SEPARATOR}/] ? config.assets_dir : config.stylesheets_dir, joined_stylesheet_name) - unless ActionController::Base.perform_caching && File.exists?(joined_stylesheet_path) + unless config.perform_caching && File.exists?(joined_stylesheet_path) write_asset_file_contents(joined_stylesheet_path, compute_stylesheet_paths(sources, recursive)) end stylesheet_tag(joined_stylesheet_name, options) diff --git a/actionpack/lib/action_view/helpers/capture_helper.rb b/actionpack/lib/action_view/helpers/capture_helper.rb index 75fc2fddeb..03c7ba5a87 100644 --- a/actionpack/lib/action_view/helpers/capture_helper.rb +++ b/actionpack/lib/action_view/helpers/capture_helper.rb @@ -140,7 +140,7 @@ module ActionView def with_output_buffer(buf = nil) #:nodoc: unless buf buf = ActionView::OutputBuffer.new - buf.force_encoding(output_buffer.encoding) if buf.respond_to?(:force_encoding) + buf.force_encoding(output_buffer.encoding) if output_buffer && buf.respond_to?(:force_encoding) end self.output_buffer, old_buffer = buf, output_buffer yield diff --git a/actionpack/lib/action_view/helpers/prototype_helper.rb b/actionpack/lib/action_view/helpers/prototype_helper.rb index 4d6ea7dfb2..dc3c6d88f5 100644 --- a/actionpack/lib/action_view/helpers/prototype_helper.rb +++ b/actionpack/lib/action_view/helpers/prototype_helper.rb @@ -180,7 +180,6 @@ module ActionView # #include_helpers_from_context has nothing to overwrite. class JavaScriptGenerator #:nodoc: def initialize(context, &block) #:nodoc: - context._evaluate_assigns_and_ivars @context, @lines = context, [] @context.update_details(:formats => [:js, :html]) do include_helpers_from_context diff --git a/actionpack/lib/action_view/helpers/tag_helper.rb b/actionpack/lib/action_view/helpers/tag_helper.rb index 8ae2e5f28f..9b4cacd4d7 100644 --- a/actionpack/lib/action_view/helpers/tag_helper.rb +++ b/actionpack/lib/action_view/helpers/tag_helper.rb @@ -109,7 +109,7 @@ module ActionView def content_tag_string(name, content, options, escape = true) tag_options = tag_options(options, escape) if options - ("<#{name}#{tag_options}>".html_safe << content.to_s).safe_concat("</#{name}>") + "<#{name}#{tag_options}>#{ERB::Util.h(content)}</#{name}>".html_safe end def tag_options(options, escape = true) diff --git a/actionpack/lib/action_view/helpers/url_helper.rb b/actionpack/lib/action_view/helpers/url_helper.rb index ae1385f3b7..131e950b18 100644 --- a/actionpack/lib/action_view/helpers/url_helper.rb +++ b/actionpack/lib/action_view/helpers/url_helper.rb @@ -224,7 +224,7 @@ module ActionView end href_attr = "href=\"#{url}\"" unless href - ("<a #{href_attr}#{tag_options}>".html_safe << (name || url)).safe_concat("</a>") + "<a #{href_attr}#{tag_options}>#{ERB::Util.h(name || url)}</a>".html_safe end end diff --git a/actionpack/lib/action_view/lookup_context.rb b/actionpack/lib/action_view/lookup_context.rb index 27ee8b23c9..8eb17bf8f1 100644 --- a/actionpack/lib/action_view/lookup_context.rb +++ b/actionpack/lib/action_view/lookup_context.rb @@ -38,17 +38,18 @@ module ActionView register_detail(:locale) { [I18n.locale] } class DetailsKey #:nodoc: - attr_reader :details alias :eql? :equal? + alias :object_hash :hash + attr_reader :hash @details_keys = Hash.new def self.get(details) - @details_keys[details] ||= new(details) + @details_keys[details] ||= new end - def initialize(details) - @details, @hash = details, details.hash + def initialize + @hash = object_hash end end @@ -70,6 +71,7 @@ module ActionView def find(name, prefix = nil, partial = false) @view_paths.find(name, prefix, partial, details, details_key) end + alias :find_template :find def find_all(name, prefix = nil, partial = false) @view_paths.find_all(name, prefix, partial, details, details_key) @@ -78,6 +80,7 @@ module ActionView def exists?(name, prefix = nil, partial = false) @view_paths.exists?(name, prefix, partial, details, details_key) end + alias :template_exists? :exists? # Add fallbacks to the view paths. Useful in cases you are rendering a :file. def with_fallbacks diff --git a/actionpack/lib/action_view/render/layouts.rb b/actionpack/lib/action_view/render/layouts.rb index e9252dba9e..11ff05ce5b 100644 --- a/actionpack/lib/action_view/render/layouts.rb +++ b/actionpack/lib/action_view/render/layouts.rb @@ -1,8 +1,5 @@ -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 @@ -46,13 +43,13 @@ module ActionView # 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: + def find_layout(layout) #:nodoc: begin layout =~ /^\// ? - with_fallbacks { find(layout) } : find(layout) + with_fallbacks { find_template(layout) } : find_template(layout) rescue ActionView::MissingTemplate => e update_details(:formats => nil) do - raise unless exists?(layout) + raise unless template_exists?(layout) end end end diff --git a/actionpack/lib/action_view/render/partials.rb b/actionpack/lib/action_view/render/partials.rb index d34ab0354c..17d16556b9 100644 --- a/actionpack/lib/action_view/render/partials.rb +++ b/actionpack/lib/action_view/render/partials.rb @@ -294,7 +294,7 @@ module ActionView def find_template(path=@path) return path unless path.is_a?(String) prefix = @view.controller_path unless path.include?(?/) - @view.find(path, prefix, true) + @view.find_template(path, prefix, true) end def partial_path(object = @object) diff --git a/actionpack/lib/action_view/render/rendering.rb b/actionpack/lib/action_view/render/rendering.rb index 47ea70f5ad..310efe40e2 100644 --- a/actionpack/lib/action_view/render/rendering.rb +++ b/actionpack/lib/action_view/render/rendering.rb @@ -12,14 +12,18 @@ module ActionView # # If no options hash is passed or :update specified, the default is to render a partial and use the second parameter # as the locals hash. - def render(options = {}, locals = {}, &block) #:nodoc: + def render(options = {}, locals = {}, &block) case options when Hash if block_given? content = _render_partial(options.merge(:partial => options[:layout]), &block) safe_concat(content) + elsif options.key?(:partial) + _render_partial(options) else - _render(options) + template = _determine_template(options) + self.formats = template.formats + _render_template(template, options[:layout], options) end when :update update_page(&block) @@ -28,44 +32,18 @@ module ActionView end end - # This is the API to render a ViewContext's template from a controller. - 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 - - # 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 - # 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?(:_template) - options[:_template] + Template::Text.new(options[:text], formats.try(:first)) elsif options.key?(:file) - with_fallbacks { find(options[:file], options[:prefix]) } + with_fallbacks { find_template(options[:file], options[:prefix]) } elsif options.key?(:template) - find(options[:template], options[:prefix]) + options[:template].respond_to?(:render) ? + options[:template] : find_template(options[:template], options[:prefix]) end end @@ -73,7 +51,7 @@ module ActionView # supplied as well. def _render_template(template, layout = nil, options = {}) #:nodoc: locals = options[:locals] || {} - layout = _find_layout(layout) if layout + layout = find_layout(layout) if layout ActiveSupport::Notifications.instrument("action_view.render_template", :identifier => template.identifier, :layout => layout.try(:identifier)) do @@ -89,6 +67,5 @@ module ActionView content end end - end end diff --git a/actionpack/lib/action_view/template/handlers/rjs.rb b/actionpack/lib/action_view/template/handlers/rjs.rb index 63e7dc0902..128be5077c 100644 --- a/actionpack/lib/action_view/template/handlers/rjs.rb +++ b/actionpack/lib/action_view/template/handlers/rjs.rb @@ -6,8 +6,7 @@ module ActionView self.default_format = Mime::JS def compile(template) - "controller.response.content_type ||= Mime::JS;" + - "update_page do |page|;#{template.source}\nend" + "update_page do |page|;#{template.source}\nend" end def default_format diff --git a/actionpack/lib/action_view/template/text.rb b/actionpack/lib/action_view/template/text.rb index df394b0fb0..269340514c 100644 --- a/actionpack/lib/action_view/template/text.rb +++ b/actionpack/lib/action_view/template/text.rb @@ -1,10 +1,12 @@ module ActionView #:nodoc: class Template class Text < String #:nodoc: - def initialize(string, content_type = nil) + attr_accessor :mime_type + + def initialize(string, mime_type = nil) super(string.to_s) - @content_type = Mime[content_type] || content_type if content_type - @content_type ||= Mime::TEXT + @mime_type = Mime[mime_type] || mime_type if mime_type + @mime_type ||= Mime::TEXT end def identifier @@ -19,12 +21,8 @@ module ActionView #:nodoc: to_s end - def mime_type - @content_type - end - def formats - [@content_type.to_sym] + [@mime_type.to_sym] end def partial? diff --git a/actionpack/test/abstract/layouts_test.rb b/actionpack/test/abstract/layouts_test.rb index 65a50807fd..f580ad40f7 100644 --- a/actionpack/test/abstract/layouts_test.rb +++ b/actionpack/test/abstract/layouts_test.rb @@ -8,210 +8,158 @@ module AbstractControllerTests include AbstractController::Rendering include AbstractController::Layouts - def _prefix - "template" - end - self.view_paths = [ActionView::FixtureResolver.new( - "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 %>" + "layouts/with_false_layout.erb" => "False Layout <%= yield %>", + "abstract_controller_tests/layouts/with_string_implied_child.erb" => + "With Implied <%= yield %>" )] end - + class Blank < Base - self.view_paths = ActionView::FixtureResolver.new("template/index.erb" => "Hello blank!") + self.view_paths = [] def index - render + render :template => ActionView::Template::Text.new("Hello blank!") 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 + render :template => ActionView::Template::Text.new("Hello string!") end def overwrite_default - render :layout => :default + render :template => ActionView::Template::Text.new("Hello string!"), :layout => :default end def overwrite_false - render :layout => false + render :template => ActionView::Template::Text.new("Hello string!"), :layout => false end def overwrite_string - render :layout => "overwrite" + render :template => ActionView::Template::Text.new("Hello string!"), :layout => "overwrite" end def overwrite_skip render :text => "Hello text!" end end - + class WithStringChild < WithString end - + class WithStringOverriddenChild < WithString layout "hello_override" end - + class WithNilChild < WithString layout nil - end - + end + class WithStringImpliedChild < WithString end - + class WithChildOfImplied < WithStringImpliedChild end class WithProc < Base layout proc { |c| "overwrite" } - append_view_path ActionView::FixtureResolver.new( - "template/index.erb" => "Hello proc!" - ) - def index - render + render :template => ActionView::Template::Text.new("Hello proc!") end end class WithSymbol < Base layout :hello - append_view_path ActionView::FixtureResolver.new( - "template/index.erb" => "Hello symbol!" - ) - def index - render + render :template => ActionView::Template::Text.new("Hello symbol!") end - private - def hello "overwrite" end end - + class WithSymbolReturningString < Base layout :no_hello - append_view_path ActionView::FixtureResolver.new( - "template/index.erb" => "Hello missing symbol!" - ) - def index - render + render :template => ActionView::Template::Text.new("Hello missing symbol!") end - private - def no_hello nil end end - + class WithSymbolReturningNil < Base layout :nilz - append_view_path ActionView::FixtureResolver.new( - "template/index.erb" => "Hello nilz!" - ) - def index - render - end - - def nilz + render :template => ActionView::Template::Text.new("Hello 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 + render :template => ActionView::Template::Text.new("Hello nilz!") end - + def objekt Object.new end - end - + end + class WithSymbolAndNoMethod < Base layout :no_method - append_view_path ActionView::FixtureResolver.new( - "template/index.erb" => "Hello boom!" - ) - def index - render + render :template => ActionView::Template::Text.new("Hello boom!") end end - + class WithMissingLayout < Base layout "missing" - append_view_path ActionView::FixtureResolver.new( - "template/index.erb" => "Hello missing!" - ) - def index - render + render :template => ActionView::Template::Text.new("Hello missing!") end end - + class WithFalseLayout < Base layout false - append_view_path ActionView::FixtureResolver.new( - "template/index.erb" => "Hello false!" - ) - def index - render + render :template => ActionView::Template::Text.new("Hello false!") end end - + class WithNilLayout < Base layout nil - append_view_path ActionView::FixtureResolver.new( - "template/index.erb" => "Hello nil!" - ) - def index - render + render :template => ActionView::Template::Text.new("Hello nil!") end end - + class TestBase < ActiveSupport::TestCase test "when no layout is specified, and no default is available, render without a layout" do controller = Blank.new controller.process(:index) assert_equal "Hello blank!", controller.response_body end - + test "when layout is specified as a string, render with that layout" do controller = WithString.new controller.process(:index) @@ -245,13 +193,13 @@ module AbstractControllerTests test "when layout is specified as a string, but the layout is missing, raise an exception" do assert_raises(ActionView::MissingTemplate) { WithMissingLayout.new.process(:index) } end - + test "when layout is specified as false, do not use a layout" do controller = WithFalseLayout.new controller.process(:index) assert_equal "Hello false!", controller.response_body end - + test "when layout is specified as nil, do not use a layout" do controller = WithNilLayout.new controller.process(:index) @@ -263,58 +211,58 @@ module AbstractControllerTests controller.process(:index) assert_equal "Overwrite Hello proc!", controller.response_body end - + test "when layout is specified as a symbol, call the requested method and use the layout returned" do controller = WithSymbol.new controller.process(:index) assert_equal "Overwrite Hello symbol!", controller.response_body end - + test "when layout is specified as a symbol and the method returns nil, don't use a layout" do controller = WithSymbolReturningNil.new controller.process(:index) assert_equal "Hello nilz!", controller.response_body end - + test "when the layout is specified as a symbol and the method doesn't exist, raise an exception" do assert_raises(NoMethodError) { WithSymbolAndNoMethod.new.process(:index) } end - + test "when the layout is specified as a symbol and the method returns something besides a string/false/nil, raise an exception" do assert_raises(ArgumentError) { WithSymbolReturningObj.new.process(:index) } end - + test "when a child controller does not have a layout, use the parent controller layout" do controller = WithStringChild.new controller.process(:index) assert_equal "With String Hello string!", controller.response_body end - + test "when a child controller has specified a layout, use that layout and not the parent controller layout" do controller = WithStringOverriddenChild.new controller.process(:index) assert_equal "With Override Hello string!", controller.response_body end - + test "when a child controller has an implied layout, use that layout and not the parent controller layout" do controller = WithStringImpliedChild.new controller.process(:index) assert_equal "With Implied Hello string!", controller.response_body end - + test "when a child controller specifies layout nil, do not use the parent layout" do controller = WithNilChild.new controller.process(:index) assert_equal "Hello string!", controller.response_body end - + test "when a grandchild has no layout specified, the child has an implied layout, and the " \ "parent has specified a layout, use the child controller layout" do controller = WithChildOfImplied.new controller.process(:index) assert_equal "With Implied Hello string!", controller.response_body end - + test "raises an exception when specifying layout true" do assert_raises ArgumentError do Object.class_eval do @@ -326,4 +274,4 @@ module AbstractControllerTests end end end -end +end
\ No newline at end of file diff --git a/actionpack/test/controller/caching_test.rb b/actionpack/test/controller/caching_test.rb index a3c8fdbb6e..a792752ef4 100644 --- a/actionpack/test/controller/caching_test.rb +++ b/actionpack/test/controller/caching_test.rb @@ -634,6 +634,19 @@ class FragmentCachingTest < ActionController::TestCase assert_equal 'generated till now -> fragment content', buffer end + def test_html_safety + assert_nil @store.read('views/name') + content = 'value'.html_safe + assert_equal content, @controller.write_fragment('name', content) + + cached = @store.read('views/name') + assert_equal content, cached + assert_equal String, cached.class + + html_safe = @controller.read_fragment('name') + assert_equal content, html_safe + assert html_safe.html_safe? + end end class FunctionalCachingController < CachingController diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb index e3c4869391..20fcb87da6 100644 --- a/actionpack/test/controller/render_test.rb +++ b/actionpack/test/controller/render_test.rb @@ -617,6 +617,15 @@ class TestController < ActionController::Base raise end + before_filter :only => :render_with_filters do + request.format = :xml + end + + # Ensure that the before filter is executed *before* self.formats is set. + def render_with_filters + render :action => :formatted_xml_erb + end + private def determine_layout @@ -1034,6 +1043,11 @@ class RenderTest < ActionController::TestCase assert_equal "<html>Hello world!</html>", @response.body end + def test_render_with_filters + get :render_with_filters + assert_equal "<test>passed formatted xml erb</test>", @response.body + end + # :ported: def test_double_render assert_raise(ActionController::DoubleRenderError) { get :double_render } diff --git a/actionpack/test/controller/resources_test.rb b/actionpack/test/controller/resources_test.rb index f60045bba6..17c645c04c 100644 --- a/actionpack/test/controller/resources_test.rb +++ b/actionpack/test/controller/resources_test.rb @@ -16,6 +16,7 @@ class AccountsController < ResourcesController; end class AdminController < ResourcesController; end class ProductsController < ResourcesController; end class ImagesController < ResourcesController; end +class PreferencesController < ResourcesController; end module Backoffice class ProductsController < ResourcesController; end @@ -1125,6 +1126,12 @@ class ResourcesTest < ActionController::TestCase end end + def test_singleton_resource_name_is_not_singularized + with_singleton_resources(:preferences) do + assert_singleton_restful_for :preferences + end + end + protected def with_restful_routing(*args) with_routing do |set| diff --git a/actionpack/test/template/asset_tag_helper_test.rb b/actionpack/test/template/asset_tag_helper_test.rb index d9a89959da..c471df861d 100644 --- a/actionpack/test/template/asset_tag_helper_test.rb +++ b/actionpack/test/template/asset_tag_helper_test.rb @@ -50,7 +50,7 @@ class AssetTagHelperTest < ActionView::TestCase end def teardown - ActionController::Base.perform_caching = false + config.perform_caching = false ENV.delete('RAILS_ASSET_ID') end @@ -141,7 +141,6 @@ class AssetTagHelperTest < ActionView::TestCase ImageLinkToTag = { %(image_tag("xml.png")) => %(<img alt="Xml" src="/images/xml.png" />), - %(image_tag("..jpg")) => %(<img alt="..jpg" src="/images/..jpg" />), %(image_tag("rss.gif", :alt => "rss syndication")) => %(<img alt="rss syndication" src="/images/rss.gif" />), %(image_tag("gold.png", :size => "45x70")) => %(<img alt="Gold" height="70" src="/images/gold.png" width="45" />), %(image_tag("gold.png", "size" => "45x70")) => %(<img alt="Gold" height="70" src="/images/gold.png" width="45" />), @@ -422,7 +421,7 @@ class AssetTagHelperTest < ActionView::TestCase def test_caching_javascript_include_tag_when_caching_on ENV["RAILS_ASSET_ID"] = "" @controller.config.asset_host = 'http://a0.example.com' - ActionController::Base.perform_caching = true + config.perform_caching = true assert_dom_equal( %(<script src="http://a0.example.com/javascripts/all.js" type="text/javascript"></script>), @@ -454,7 +453,7 @@ class AssetTagHelperTest < ActionView::TestCase def test_caching_javascript_include_tag_when_caching_on_with_proc_asset_host ENV['RAILS_ASSET_ID'] = '' @controller.config.asset_host = Proc.new { |source| "http://a#{source.length}.example.com" } - ActionController::Base.perform_caching = true + config.perform_caching = true assert_equal '/javascripts/scripts.js'.length, 23 assert_dom_equal( @@ -477,7 +476,7 @@ class AssetTagHelperTest < ActionView::TestCase "#{request.protocol}assets#{source.length}.example.com" end } - ActionController::Base.perform_caching = true + config.perform_caching = true assert_equal '/javascripts/vanilla.js'.length, 23 assert_dom_equal( @@ -517,7 +516,7 @@ class AssetTagHelperTest < ActionView::TestCase end end.new - ActionController::Base.perform_caching = true + config.perform_caching = true assert_equal '/javascripts/vanilla.js'.length, 23 assert_dom_equal( @@ -548,7 +547,7 @@ class AssetTagHelperTest < ActionView::TestCase def test_caching_javascript_include_tag_when_caching_on_and_using_subdirectory ENV["RAILS_ASSET_ID"] = "" @controller.config.asset_host = 'http://a%d.example.com' - ActionController::Base.perform_caching = true + config.perform_caching = true hash = '/javascripts/cache/money.js'.hash % 4 assert_dom_equal( @@ -564,7 +563,7 @@ class AssetTagHelperTest < ActionView::TestCase def test_caching_javascript_include_tag_with_all_and_recursive_puts_defaults_at_the_start_of_the_file ENV["RAILS_ASSET_ID"] = "" @controller.config.asset_host = 'http://a0.example.com' - ActionController::Base.perform_caching = true + config.perform_caching = true assert_dom_equal( %(<script src="http://a0.example.com/javascripts/combined.js" type="text/javascript"></script>), @@ -585,7 +584,7 @@ class AssetTagHelperTest < ActionView::TestCase def test_caching_javascript_include_tag_with_all_puts_defaults_at_the_start_of_the_file ENV["RAILS_ASSET_ID"] = "" @controller.config.asset_host = 'http://a0.example.com' - ActionController::Base.perform_caching = true + config.perform_caching = true assert_dom_equal( %(<script src="http://a0.example.com/javascripts/combined.js" type="text/javascript"></script>), @@ -606,7 +605,7 @@ class AssetTagHelperTest < ActionView::TestCase def test_caching_javascript_include_tag_with_relative_url_root ENV["RAILS_ASSET_ID"] = "" @controller.config.relative_url_root = "/collaboration/hieraki" - ActionController::Base.perform_caching = true + config.perform_caching = true assert_dom_equal( %(<script src="/collaboration/hieraki/javascripts/all.js" type="text/javascript"></script>), @@ -629,7 +628,7 @@ class AssetTagHelperTest < ActionView::TestCase def test_caching_javascript_include_tag_when_caching_off ENV["RAILS_ASSET_ID"] = "" - ActionController::Base.perform_caching = false + config.perform_caching = false assert_dom_equal( %(<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/application.js" type="text/javascript"></script>\n<script src="/javascripts/bank.js" type="text/javascript"></script>\n<script src="/javascripts/robber.js" type="text/javascript"></script>\n<script src="/javascripts/version.1.0.js" type="text/javascript"></script>), @@ -658,7 +657,7 @@ class AssetTagHelperTest < ActionView::TestCase def test_caching_javascript_include_tag_when_caching_on_and_missing_javascript_file ENV["RAILS_ASSET_ID"] = "" - ActionController::Base.perform_caching = true + config.perform_caching = true assert_raise(Errno::ENOENT) { javascript_include_tag('bank', 'robber', 'missing_security_guard', :cache => true) @@ -675,7 +674,7 @@ class AssetTagHelperTest < ActionView::TestCase def test_caching_javascript_include_tag_when_caching_off_and_missing_javascript_file ENV["RAILS_ASSET_ID"] = "" - ActionController::Base.perform_caching = false + config.perform_caching = false assert_raise(Errno::ENOENT) { javascript_include_tag('bank', 'robber', 'missing_security_guard', :cache => true) @@ -693,7 +692,7 @@ class AssetTagHelperTest < ActionView::TestCase def test_caching_stylesheet_link_tag_when_caching_on ENV["RAILS_ASSET_ID"] = "" @controller.config.asset_host = 'http://a0.example.com' - ActionController::Base.perform_caching = true + config.perform_caching = true assert_dom_equal( %(<link href="http://a0.example.com/stylesheets/all.css" media="screen" rel="stylesheet" type="text/css" />), @@ -760,7 +759,7 @@ class AssetTagHelperTest < ActionView::TestCase def test_caching_stylesheet_link_tag_when_caching_on_and_missing_css_file ENV["RAILS_ASSET_ID"] = "" - ActionController::Base.perform_caching = true + config.perform_caching = true assert_raise(Errno::ENOENT) { stylesheet_link_tag('bank', 'robber', 'missing_security_guard', :cache => true) @@ -781,7 +780,7 @@ class AssetTagHelperTest < ActionView::TestCase def test_caching_stylesheet_link_tag_when_caching_off_and_missing_css_file ENV["RAILS_ASSET_ID"] = "" - ActionController::Base.perform_caching = false + config.perform_caching = false assert_raise(Errno::ENOENT) { stylesheet_link_tag('bank', 'robber', 'missing_security_guard', :cache => true) @@ -803,7 +802,7 @@ class AssetTagHelperTest < ActionView::TestCase def test_caching_stylesheet_link_tag_when_caching_on_with_proc_asset_host ENV["RAILS_ASSET_ID"] = "" @controller.config.asset_host = Proc.new { |source| "http://a#{source.length}.example.com" } - ActionController::Base.perform_caching = true + config.perform_caching = true assert_equal '/stylesheets/styles.css'.length, 23 assert_dom_equal( @@ -820,7 +819,7 @@ class AssetTagHelperTest < ActionView::TestCase def test_caching_stylesheet_link_tag_with_relative_url_root ENV["RAILS_ASSET_ID"] = "" @controller.config.relative_url_root = "/collaboration/hieraki" - ActionController::Base.perform_caching = true + config.perform_caching = true assert_dom_equal( %(<link href="/collaboration/hieraki/stylesheets/all.css" media="screen" rel="stylesheet" type="text/css" />), @@ -845,7 +844,7 @@ class AssetTagHelperTest < ActionView::TestCase def test_caching_stylesheet_include_tag_when_caching_off ENV["RAILS_ASSET_ID"] = "" - ActionController::Base.perform_caching = false + config.perform_caching = false assert_dom_equal( %(<link href="/stylesheets/bank.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/robber.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/version.1.0.css" media="screen" rel="stylesheet" type="text/css" />), diff --git a/actionpack/test/template/capture_helper_test.rb b/actionpack/test/template/capture_helper_test.rb index 2017a18806..f887c9ab5b 100644 --- a/actionpack/test/template/capture_helper_test.rb +++ b/actionpack/test/template/capture_helper_test.rb @@ -12,4 +12,10 @@ class CaptureHelperTest < ActionView::TestCase assert content_for?(:title) assert ! content_for?(:something_else) end + + def test_with_output_buffer_does_not_assume_there_is_an_output_buffer + av = ActionView::Base.new + assert_nil av.output_buffer + assert_equal "", av.with_output_buffer {} + end end |