<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>lib/merb-core/core_ext/virtual_file.rb</filename>
    </added>
    <added>
      <filename>lib/merb-core/rack/adapter/swiftiplied_mongrel.rb</filename>
    </added>
    <added>
      <filename>lib/merb-core/rack/middleware/path_prefix.rb</filename>
    </added>
    <added>
      <filename>lib/merb-core/rack/middleware/profiler.rb</filename>
    </added>
    <added>
      <filename>lib/merb-core/rack/middleware/static.rb</filename>
    </added>
    <added>
      <filename>spec/public/abstract_controller/controllers/cousins.rb</filename>
    </added>
    <added>
      <filename>spec/public/abstract_controller/controllers/views/partial/with_absolute_partial/_partial.erb</filename>
    </added>
    <added>
      <filename>spec/public/abstract_controller/controllers/views/partial/with_absolute_partial/index.erb</filename>
    </added>
    <added>
      <filename>spec/public/controller/controllers/views/layout/custom_arg.json.erb</filename>
    </added>
    <added>
      <filename>spec/public/core_ext/fixtures/core_ext_dependency.rb</filename>
    </added>
    <added>
      <filename>spec/public/core_ext/kernel_spec.rb</filename>
    </added>
    <added>
      <filename>spec/public/core_ext/spec_helper.rb</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -1,4 +1,4 @@
-Copyright (c) 2008 Ezra Zygmuntowicz
+Copyright (c) 2008 Engine Yard Inc.
 
 Permission is hereby granted, free of charge, to any person obtaining
 a copy of this software and associated documentation files (the</diff>
      <filename>LICENSE</filename>
    </modified>
    <modified>
      <diff>@@ -15,7 +15,7 @@ Goals of this release:
   
 To familiarize yourself with how a merb-core application might look,
 use merb-gen (from merb-more) to generate a few apps:
-$ merb-gen myapp                   # a &quot;normal&quot; merb app
-$ merb-gen myapp --flat            # a flattened app
-$ merb-gen myapp --very-flat       # a single-file app
+$ merb-gen app myapp                   # a &quot;normal&quot; merb app
+$ merb-gen app myapp --flat            # a flattened app
+$ merb-gen app myapp --very-flat       # a single-file app
 </diff>
      <filename>README</filename>
    </modified>
    <modified>
      <diff>@@ -26,8 +26,8 @@ require 'lib/merb-core/tasks/merb_rake_helper'
 ##############################################################################
 CLEAN.include [&quot;**/.*.sw?&quot;, &quot;pkg&quot;, &quot;lib/*.bundle&quot;, &quot;*.gem&quot;, &quot;doc/rdoc&quot;, &quot;.config&quot;, &quot;coverage&quot;, &quot;cache&quot;]
 
-desc &quot;Packages up Merb.&quot;
-task :default =&gt; :package
+desc &quot;Run the specs.&quot;
+task :default =&gt; :specs
 
 task :merb =&gt; [:clean, :rdoc, :package]
 </diff>
      <filename>Rakefile</filename>
    </modified>
    <modified>
      <diff>@@ -5,10 +5,8 @@ module Merb
     # def self.subclasses
     #---
     # @semipublic
-    cattr_accessor :subclasses, :after_load_callbacks, :before_load_callbacks
-    self.subclasses = []
-    self.after_load_callbacks = []
-    self.before_load_callbacks = []
+    cattr_accessor :subclasses, :after_load_callbacks, :before_load_callbacks, :finished
+    self.subclasses, self.after_load_callbacks, self.before_load_callbacks, self.finished = [], [], [], []
 
     class &lt;&lt; self
 
@@ -65,9 +63,21 @@ module Merb
           bootloader = subclasses.shift
           Merb.logger.debug!(&quot;Loading: #{bootloader}&quot;) if ENV['DEBUG']
           Object.full_const_get(bootloader).run
+          self.finished &lt;&lt; bootloader
         end
         self.subclasses = subklasses
       end
+      
+      # Determines whether or not a specific bootloader has finished yet.
+      #
+      # ==== Parameters
+      # bootloader&lt;String, Class&gt;:: The name of the bootloader to check.
+      #
+      # ==== Returns
+      # Boolean:: Whether or not the bootloader has finished.
+      def finished?(bootloader)
+        self.finished.include?(bootloader.to_s)
+      end
 
       # Set up the default framework
       #
@@ -77,7 +87,7 @@ module Merb
       #---
       # @public
       def default_framework
-        %w[view model controller helper mailer part].each do |component|
+        %w[view model helper controller mailer part].each do |component|
           Merb.push_path(component.to_sym, Merb.root_path(&quot;app/#{component}s&quot;))
         end
         Merb.push_path(:application,  Merb.root_path(&quot;app/controllers/application.rb&quot;))
@@ -155,7 +165,10 @@ end
 # Setup some useful defaults
 class Merb::BootLoader::Defaults &lt; Merb::BootLoader
   def self.run
-    Merb::Request.browser_method_workarounds &lt;&lt; &quot;_method&quot;
+    Merb::Request.http_method_overrides.concat([
+      proc { |c| c.params[:_method] },
+      proc { |c| c.env['HTTP_X_HTTP_METHOD_OVERRIDE'] }
+    ])
   end
 end
 
@@ -185,9 +198,11 @@ end
 #
 # ==== Example
 #   Merb::Config[:framework] = {
-#     :view =&gt; Merb.root / &quot;views&quot;
-#     :model =&gt; Merb.root / &quot;models&quot;
-#     :lib =&gt; Merb.root / &quot;lib&quot;
+#     :view   =&gt; Merb.root / &quot;views&quot;,
+#     :model  =&gt; Merb.root / &quot;models&quot;,
+#     :lib    =&gt; Merb.root / &quot;lib&quot;,
+#     :public =&gt; [Merb.root / &quot;public&quot;, nil]
+#     :router =&gt; [Merb.root / &quot;config&quot;, &quot;router.rb&quot;]
 #   }
 #
 # That will set up a flat directory structure with the config files and
@@ -212,8 +227,8 @@ class Merb::BootLoader::BuildFramework &lt; Merb::BootLoader
         Merb::BootLoader.default_framework
       end
       (Merb::Config[:framework] || {}).each do |name, path|
-        path = [path].flatten
-        Merb.push_path(name, Merb.root_path(path.first), path[1])
+        path = Array(path)
+        Merb.push_path(name, path.first, path.length == 2 ? path[1] : &quot;**/*.rb&quot;)
       end
     end
   end
@@ -369,6 +384,7 @@ class Merb::BootLoader::LoadClasses &lt; Merb::BootLoader
     # Reload the router to regenerate all routes.
     def reload_router!
       if File.file?(router_file = Merb.dir_for(:router) / Merb.glob_for(:router))
+        Merb::Router.reset!
         reload router_file
       end
     end
@@ -465,14 +481,14 @@ class Merb::BootLoader::Templates &lt; Merb::BootLoader
     # Loads the templates into the Merb::InlineTemplates module.
     def run
       template_paths.each do |path|
-        Merb::Template.inline_template(path)
+        Merb::Template.inline_template(File.open(path))
       end
     end
 
     # ==== Returns
     # Array[String]:: Template files found.
     def template_paths
-      extension_glob = &quot;{#{Merb::Template::EXTENSIONS.keys.join(',')}}&quot;
+      extension_glob = &quot;{#{Merb::Template.template_extensions.join(',')}}&quot;
 
       # This gets all templates set in the controllers template roots
       # We separate the two maps because most of controllers will have
@@ -550,10 +566,8 @@ class Merb::BootLoader::MixinSessionContainer &lt; Merb::BootLoader
       if [&quot;&quot;, &quot;false&quot;, &quot;none&quot;].include?(session_store)
         Merb.logger.warn &quot;Not Using Sessions&quot;
       elsif reg = Merb.registered_session_types[session_store]
-        if session_store == &quot;cookie&quot;
-          Merb::BootLoader::MixinSessionContainer.check_for_secret_key
-          Merb::BootLoader::MixinSessionContainer.check_for_session_id_key
-        end
+        Merb::BootLoader::MixinSessionContainer.check_for_secret_key if session_store == &quot;cookie&quot;
+        Merb::BootLoader::MixinSessionContainer.check_for_session_id_key
         require reg[:file]
         include ::Merb::SessionMixin
         Merb.logger.warn reg[:description]</diff>
      <filename>lib/merb-core/bootloader.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,5 +1,15 @@
-# Note that the over-use of &quot;_&quot; in Controller methods is to avoid collisions
-# with helpers, which will be pulled directly into controllers from now on.
+# ==== Why do we use Underscores?
+# In Merb, views are actually methods on controllers. This provides
+# not-insignificant speed benefits, as well as preventing us from
+# needing to copy over instance variables, which we think is proof
+# that everything belongs in one class to begin with.
+#
+# Unfortunately, this means that view helpers need to be included
+# into the &lt;strong&gt;Controller&lt;/strong&gt; class. To avoid causing confusion
+# when your helpers potentially conflict with our instance methods,
+# we use an _ to disambiguate. As long as you don't begin your helper
+# methods with _, you only need to worry about conflicts with Merb
+# methods that are part of the public API.
 #
 # ==== Filters
 # #before is a class method that allows you to specify before filters in
@@ -71,7 +81,8 @@ class Merb::AbstractController
   include Merb::RenderMixin
   include Merb::InlineTemplates
   
-  class_inheritable_accessor :_before_filters, :_after_filters, :_layout, :_template_root
+  class_inheritable_accessor :_layout, :_template_root
+  class_inheritable_array :_before_filters, :_after_filters
   
   FILTER_OPTIONS = [:only, :exclude, :if, :unless, :with]
 
@@ -121,6 +132,18 @@ class Merb::AbstractController
     controller ? &quot;#{controller}/#{context}&quot; : context
   end
 
+  # The location to look for a template - stub method for particular behaviour.
+  #
+  # ==== Parameters
+  # template&lt;String&gt;:: The absolute path to a template - without template extension.
+  # type&lt;~to_s&gt;::
+  #    The mime-type of the template that will be rendered. Defaults to nil.
+  #
+  # @public
+  def _absolute_template_location(template, type)
+    template
+  end
+
   # ==== Returns
   # roots&lt;Array[Array]&gt;::
   #   Template roots as pairs of template root path and template location
@@ -429,6 +452,27 @@ class Merb::AbstractController
     request.protocol + request.host + url(name, rparams)
   end
 
+  # Calls the capture method for the selected template engine.
+  #
+  # ==== Parameters
+  # *args:: Arguments to pass to the block.
+  # &amp;block:: The template block to call.
+  #
+  # ==== Returns
+  # String:: The output of the block.
+  def capture(*args, &amp;block)
+    send(&quot;capture_#{@_engine}&quot;, *args, &amp;block)
+  end
+
+  # Calls the concatenate method for the selected template engine.
+  #
+  # ==== Parameters
+  # str&lt;String&gt;:: The string to concatenate to the buffer.
+  # binding&lt;Binding&gt;:: The binding to use for the buffer.
+  def concat(str, binding)
+    send(&quot;concat_#{@_engine}&quot;, str, binding)
+  end
+
   private
   # ==== Parameters
   # filters&lt;Array[Filter]&gt;:: The filter list that this should be added to.
@@ -503,27 +547,6 @@ class Merb::AbstractController
     return opts
   end
 
-  # Calls the capture method for the selected template engine.
-  #
-  # ==== Parameters
-  # *args:: Arguments to pass to the block.
-  # &amp;block:: The template block to call.
-  #
-  # ==== Returns
-  # String:: The output of the block.
-  def capture(*args, &amp;block)
-    send(&quot;capture_#{@_engine}&quot;, *args, &amp;block)
-  end
-
-  # Calls the concatenate method for the selected template engine.
-  #
-  # ==== Parameters
-  # str&lt;String&gt;:: The string to concatenate to the buffer.
-  # binding&lt;Binding&gt;:: The binding to use for the buffer.
-  def concat(str, binding)
-    send(&quot;concat_#{@_engine}&quot;, str, binding)
-  end
-
   # Attempts to return the partial local variable corresponding to sym.
   #
   # ==== Paramteres</diff>
      <filename>lib/merb-core/controller/abstract_controller.rb</filename>
    </modified>
    <modified>
      <diff>@@ -24,8 +24,8 @@ class Merb::Controller &lt; Merb::AbstractController
     #   The Merb::Controller inheriting from the base class.
     def inherited(klass)
       _subclasses &lt;&lt; klass.to_s
-      self._template_root = Merb.dir_for(:view) unless self._template_root
       super
+      klass._template_root = Merb.dir_for(:view) unless self._template_root
     end
 
     # Hide each of the given methods from being callable as actions.
@@ -157,6 +157,23 @@ class Merb::Controller &lt; Merb::AbstractController
   def _template_location(context, type = nil, controller = controller_name)
     controller ? &quot;#{controller}/#{context}.#{type}&quot; : &quot;#{context}.#{type}&quot;
   end
+  
+  # The location to look for a template and mime-type. This is overridden 
+  # from AbstractController, which defines a version of this that does not 
+  # involve mime-types.
+  #
+  # ==== Parameters
+  # template&lt;String&gt;:: 
+  #    The absolute path to a template - without mime and template extension.
+  #    The mime-type extension is optional - it will be appended from the 
+  #    current content type if it hasn't been added already.
+  # type&lt;~to_s&gt;::
+  #    The mime-type of the template that will be rendered. Defaults to nil.
+  #
+  # @public
+  def _absolute_template_location(template, type)
+    template.match(/\.#{type.to_s.escape_regexp}$/) ? template : &quot;#{template}.#{type}&quot;
+  end
 
   # Build a new controller.
   #
@@ -176,7 +193,7 @@ class Merb::Controller &lt; Merb::AbstractController
   # @semipublic
   def initialize(request, status=200, headers={'Content-Type' =&gt; 'text/html; charset=utf-8'})
     super()
-    @request, @status, @headers = request, status, headers
+    @request, @_status, @headers = request, status, headers
   end
 
   # Dispatch the action.
@@ -202,7 +219,10 @@ class Merb::Controller &lt; Merb::AbstractController
   end
 
   attr_reader :request, :headers
-  attr_reader :status
+  
+  def status
+    @_status
+  end
 
   # Set the response status code.
   #
@@ -210,9 +230,9 @@ class Merb::Controller &lt; Merb::AbstractController
   # s&lt;Fixnum, Symbol&gt;:: A status-code or named http-status
   def status=(s)
     if s.is_a?(Symbol) &amp;&amp; STATUS_CODES.key?(s)
-      @status = STATUS_CODES[s]
+      @_status = STATUS_CODES[s]
     elsif s.is_a?(Fixnum)
-      @status = s
+      @_status = s
     else
       raise ArgumentError, &quot;Status should be of type Fixnum or Symbol, was #{s.class}&quot;
     end</diff>
      <filename>lib/merb-core/controller/merb_controller.rb</filename>
    </modified>
    <modified>
      <diff>@@ -103,11 +103,18 @@ module Merb::RenderMixin
     # Do we have a template to try to render?
     if thing.is_a?(Symbol) || opts[:template]
 
-      template_method, template_location = _template_for(thing, content_type, controller_name, opts)
-
+      template_method, template_location = 
+        _template_for(thing, content_type, controller_name, opts[:template])
+      
       # Raise an error if there's no template
-      raise TemplateNotFound, &quot;No template found at #{template_location}.*&quot;  \
-        unless template_method &amp;&amp; self.respond_to?(template_method)
+      unless template_method &amp;&amp; self.respond_to?(template_method)
+        template_files = Merb::Template.template_extensions.map { |ext| &quot;#{template_location}.#{ext}&quot; }
+        raise TemplateNotFound, &quot;Oops! No template found. Merb was looking for #{template_files.join(', ')}&quot; + 
+          &quot;for content type '#{content_type}'. You might have mispelled the template or file name. &quot; + 
+          &quot;Registered template extensions: #{Merb::Template.template_extensions.join(', ')}. &quot; +
+          &quot;If you use Haml or some other template plugin, make sure you required Merb plugin dependency &quot; + 
+          &quot;in your init file.&quot;
+      end
 
       # Call the method in question and throw the content for later consumption by the layout
       throw_content(:for_layout, self.send(template_method))
@@ -120,8 +127,7 @@ module Merb::RenderMixin
     end
 
     # If we find a layout, use it. Otherwise, just render the content thrown for layout.
-    layout = opts[:layout] != false &amp;&amp; _get_layout(opts[:layout])
-    layout ? send(layout) : catch_content(:for_layout)
+    (layout = _get_layout(opts[:layout])) ? send(layout) : catch_content(:for_layout)
   end
 
   # Renders an object using to registered transform method based on the
@@ -172,7 +178,7 @@ module Merb::RenderMixin
   #
   # :template                a template to use for rendering
   # :layout                  a layout to use for rendering
-
+  #
   # all other options        options that will be pass to serialization method
   #                          like #to_json or #to_xml
   #
@@ -181,13 +187,13 @@ module Merb::RenderMixin
   # explicitly passed in the opts.
   #
   def display(object, thing = nil, opts = {})
-    # display @object, &quot;path/to/foo&quot; means display @object, nil, :template =&gt; &quot;path/to/foo&quot;
-    # display @object, :template =&gt; &quot;path/to/foo&quot; means display @object, nil, :template =&gt; &quot;path/to/foo&quot;
     template_opt = opts.delete(:template)
 
     case thing
+    # display @object, &quot;path/to/foo&quot; means display @object, nil, :template =&gt; &quot;path/to/foo&quot;
     when String
       template_opt, thing = thing, nil
+    # display @object, :template =&gt; &quot;path/to/foo&quot; means display @object, nil, :template =&gt; &quot;path/to/foo&quot;
     when Hash
       opts, thing = thing, nil
     end
@@ -198,6 +204,7 @@ module Merb::RenderMixin
   # If the render fails (i.e. a template was not found)
   rescue TemplateNotFound =&gt; e
     # Merge with class level default render options
+    # @todo can we find a way to refactor this out so we don't have to do it everywhere?
     opts = self.class.default_render_options.merge(opts)
 
     # Figure out what to transform and raise NotAcceptable unless there's a transform method assigned
@@ -208,29 +215,9 @@ module Merb::RenderMixin
       raise NotAcceptable, &quot;#{e.message} and your object does not respond to ##{transform}&quot;
     end
 
-    # Only use a layout if one was specified
     layout_opt = opts.delete(:layout)
-
-    if layout_opt
-      # Look for the layout under the default layout directly. If it's not found, reraise
-      # the TemplateNotFound error
-      template = _template_location(layout_opt, layout.index(&quot;.&quot;) ? content_type : nil, &quot;layout&quot;)
-      layout = _template_for(_template_root / template) ||
-        (raise TemplateNotFound, &quot;No layout found at #{_template_root / template}.*&quot;)
-
-      # If the layout was found, call it
-      send(layout)
-
-    # Otherwise, just render the transformed object
-    else
-      unless opts.empty?
-        # there are options for serialization method
-        throw_content(:for_layout, object.send(transform, opts))
-      else
-        throw_content(:for_layout, object.send(transform))
-      end
-      catch_content(:for_layout)
-    end
+    throw_content(:for_layout, opts.empty? ? object.send(transform) : object.send(transform, opts))
+    layout_opt ? send(_get_layout(layout_opt)) : catch_content(:for_layout)
   end
 
   # Render a partial template.
@@ -238,9 +225,9 @@ module Merb::RenderMixin
   # ==== Parameters
   # template&lt;~to_s&gt;::
   #   The path to the template, relative to the current controller or the
-  #   template root. If the template contains a &quot;/&quot;, Merb will search for it
-  #   relative to the template root; otherwise, Merb will search for it
-  #   relative to the current controller.
+  #   template root; absolute path will work too. If the template contains a &quot;/&quot;, 
+  #   Merb will search for it relative to the template root; otherwise, 
+  #   Merb will search for it relative to the current controller.
   # opts&lt;Hash&gt;:: A hash of options (see below)
   #
   # ==== Options (opts)
@@ -262,33 +249,36 @@ module Merb::RenderMixin
     # partial :foo becomes &quot;#{controller_name}/_foo&quot;
     # partial &quot;foo/bar&quot; becomes &quot;foo/_bar&quot;
     template = template.to_s
-    kontroller = (m = template.match(/.*(?=\/)/)) ? m[0] : controller_name
-    template = &quot;_#{File.basename(template)}&quot;
-
-    template_method, template_location = _template_for(template, opts.delete(:format) || content_type, kontroller)
+    if template =~ %r{^/}
+      template_path = File.dirname(template) / &quot;_#{File.basename(template)}&quot;
+    else
+      kontroller = (m = template.match(/.*(?=\/)/)) ? m[0] : controller_name
+      template = &quot;_#{File.basename(template)}&quot;
+    end
+    template_method, template_location = 
+      _template_for(template, opts.delete(:format) || content_type, kontroller, template_path)
 
     (@_old_partial_locals ||= []).push @_merb_partial_locals
-
-    if opts.key?(:with)
-      with = opts.delete(:with)
-      as = opts.delete(:as) || template_location.match(%r[.*/_([^\.]*)])[1]
-      @_merb_partial_locals = opts
-      sent_template = [with].flatten.map do |temp|
-        @_merb_partial_locals[as.to_sym] = temp
-        if template_method &amp;&amp; self.respond_to?(template_method)
-          send(template_method)
-        else
-          raise TemplateNotFound, &quot;Could not find template at #{template_location}.*&quot;
-        end
-      end.join
-    else
-      @_merb_partial_locals = opts
+    
+    # This handles no :with as well
+    with = [opts.delete(:with)].flatten
+    as = opts.delete(:as) || template_location.match(%r[.*/_([^\.]*)])[1]
+    
+    @_merb_partial_locals = opts
+    
+    # this handles an edge-case where the name of the partial is _foo.* and your opts
+    # have :foo as a key.
+    named_local = @_merb_partial_locals.key?(as.to_sym)
+    
+    sent_template = with.map do |temp|
+      @_merb_partial_locals[as.to_sym] = temp unless named_local
       if template_method &amp;&amp; self.respond_to?(template_method)
-        sent_template = send(template_method)
+        send(template_method)
       else
         raise TemplateNotFound, &quot;Could not find template at #{template_location}.*&quot;
       end
-    end
+    end.join
+    
     @_merb_partial_locals = @_old_partial_locals.pop
     sent_template
   end
@@ -306,34 +296,7 @@ module Merb::RenderMixin
   # Hash:: The options hash that was passed in.
   def _handle_options!(opts)
     self.status = opts[:status].to_i if opts[:status]
-    _handle_location!(opts)
-    opts
-  end
-
-  # Handle the :location option appropriately
-  #
-  # ==== Parameters
-  # opts&lt;Hash&gt;:: The options hash that was passed to the render
-  #
-  # ==== Options
-  # :location
-  #    Sets headers['Location'] to the provided URL
-  #
-  # ==== Returns
-  # Hash:: The options hash that was passed in.
-  def _handle_location!(opts)
-    if header_location = opts.delete(:location)
-      # scope it
-      use_header_url = nil
-      if header_location.is_a? String
-        # Hope they know what they're doing
-        use_header_url = header_location
-      # Removed magic url :klass, @obj detection. Reconsider adding it?
-      end
-      # If we couldn't figure anything out, best let the user know
-      raise &quot;Unable to determine `:location' given #{header_location.inspect}&quot; if use_header_url.nil?
-      headers['Location'] = use_header_url
-    end
+    headers[&quot;Location&quot;] = opts.delete(:location) if opts[:location]
     opts
   end
 
@@ -355,12 +318,16 @@ module Merb::RenderMixin
   #   one in to this method), and not found. No error will be raised if no
   #   layout was specified, and the default layouts were not found.
   def _get_layout(layout = nil)
+    return false if layout == false
+    
     layout = layout.instance_of?(Symbol) &amp;&amp; self.respond_to?(layout, true) ? send(layout) : layout
     layout = layout.to_s if layout
 
     # If a layout was provided, throw an error if it's not found
-    if layout
-      template_method, template_location = _template_for(layout, layout.index(&quot;.&quot;) ? nil : content_type, &quot;layout&quot;)
+    if layout      
+      template_method, template_location = 
+        _template_for(layout, layout.index(&quot;.&quot;) ? nil : content_type, &quot;layout&quot;)
+        
       raise TemplateNotFound, &quot;No layout found at #{template_location}&quot; unless template_method
       template_method
 
@@ -376,7 +343,7 @@ module Merb::RenderMixin
   # and template location of the first match.
   #
   # ==== Parameters
-  # context&lt;Object&gt;:: The controller action or template basename.
+  # context&lt;Object&gt;:: The controller action or template (basename or absolute path).
   # content_type&lt;~to_s&gt;:: The content type (like html or json).
   # controller&lt;~to_s&gt;:: The name of the controller. Defaults to nil.
   #
@@ -388,24 +355,47 @@ module Merb::RenderMixin
   # ==== Returns
   # Array[Symbol, String]::
   #   A pair consisting of the template method and location.
-  def _template_for(context, content_type, controller=nil, opts={})
-    template_method = nil
-    template_location = nil
-
-    self.class._template_roots.reverse_each do |root, template_location|
-      if opts[:template] # use the given template as the location context
-        template_location = root / self.send(template_location, opts[:template], content_type, nil)
-        template_method = Merb::Template.template_for(template_location)
-        break if template_method &amp;&amp; self.respond_to?(template_method)
-      end
+  def _template_for(context, content_type, controller=nil, template=nil)
+    template_method, template_location = nil, nil
+
+    # absolute path to a template (:template =&gt; &quot;/foo/bar&quot;)
+    if template.is_a?(String) &amp;&amp; template =~ %r{^/}
+      template_location = self._absolute_template_location(template, content_type)
+      return [_template_method_for(template_location), template_location]
+    end
 
-      template_location = root / (opts[:template] || self.send(template_location, context, content_type, controller))
-      template_method = Merb::Template.template_for(template_location)
-      break if template_method &amp;&amp; self.respond_to?(template_method)
+    self.class._template_roots.reverse_each do |root, template_meth|
+      # :template =&gt; &quot;foo/bar.html&quot; where root / &quot;foo/bar.html.*&quot; exists
+      if template &amp;&amp; template.is_a?(String) &amp;&amp; template.index(&quot;/&quot;)
+        template_location = root / template
+        
+      # :template =&gt; :tmpl where root / &quot;tmpl.html.*&quot; exists
+      elsif template
+        template_location = root / self.send(template_meth, template, content_type, nil)
+        
+      # :layout =&gt; &quot;foo&quot; where root / &quot;layouts&quot; / &quot;#{controller}.html.*&quot; exists        
+      else
+        template_location = root / self.send(template_meth, context, content_type, controller)
+      end
+      
+      break if template_method = _template_method_for(template_location)
     end
 
     [template_method, template_location]
   end
+  
+  # Return the template method for a location, and check to make sure the current controller
+  # actually responds to the method.
+  #
+  # ==== Parameters
+  # template_location&lt;String&gt;:: The phyical path of the template
+  #
+  # ==== Returns
+  # String:: The method, if it exists. Otherwise return nil.
+  def _template_method_for(template_location)
+    meth = Merb::Template.template_for(template_location)
+    meth &amp;&amp; self.respond_to?(meth) ? meth : nil
+  end
 
   # Called in templates to get at content thrown in another template. The
   # results of rendering a template are automatically thrown into :for_layout,</diff>
      <filename>lib/merb-core/controller/mixins/render.rb</filename>
    </modified>
    <modified>
      <diff>@@ -29,6 +29,27 @@ module Merb::Template
       path.gsub(/[^\.a-zA-Z0-9]/, &quot;__&quot;).gsub(/\./, &quot;_&quot;)
     end
 
+    # For a given path, get an IO object that responds to #path.
+    #
+    # This is so that plugins can override this if they provide
+    # mechanisms for specifying templates that are not just simple
+    # files. The plugin is responsible for ensuring that the fake
+    # path provided will work with #template_for, and thus the
+    # RenderMixin in general.
+    #
+    # ==== Parameters
+    # path&lt;String&gt;:: A full path to find a template for. This is the
+    #   path that the RenderMixin assumes it should find the template
+    #   in.
+    # 
+    # ==== Returns
+    # IO#path:: An IO object that responds to path (File or VirtualFile).
+    #---
+    # @semipublic
+    def load_template_io(path)
+      File.open(path)
+    end
+
     # Get the name of the template method for a particular path.
     #
     # ==== Parameters
@@ -45,11 +66,11 @@ module Merb::Template
       ret = 
       if Merb::Config[:reload_templates]
         file = Dir[&quot;#{path}.{#{template_extensions.join(',')}}&quot;].first
-        METHOD_LIST[path] = file ? inline_template(file) : nil
+        METHOD_LIST[path] = file ? inline_template(load_template_io(file)) : nil
       else
         METHOD_LIST[path] ||= begin
           file = Dir[&quot;#{path}.{#{template_extensions.join(',')}}&quot;].first          
-          file ? inline_template(file) : nil
+          file ? inline_template(load_template_io(file)) : nil
         end
       end
       
@@ -70,9 +91,8 @@ module Merb::Template
     # adds it to the METHOD_LIST table to speed lookup later.
     # 
     # ==== Parameters
-    # path&lt;String&gt;::
-    #   The full path of the template (minus the templating specifier) to
-    #   inline.
+    # io&lt;#path&gt;::
+    #   An IO that responds to #path (File or VirtualFile)
     # mod&lt;Module&gt;::
     #   The module to put the compiled method into. Defaults to
     #   Merb::InlineTemplates
@@ -82,10 +102,10 @@ module Merb::Template
     # must be available to instances of AbstractController that will use it.
     #---
     # @public
-    def inline_template(path, mod = Merb::InlineTemplates)
-      path = File.expand_path(path)
+    def inline_template(io, mod = Merb::InlineTemplates)
+      path = File.expand_path(io.path)
       METHOD_LIST[path.gsub(/\.[^\.]*$/, &quot;&quot;)] = 
-        engine_for(path).compile_template(path, template_name(path), mod)
+        engine_for(path).compile_template(io, template_name(path), mod)
     end
     
     # Finds the engine for a particular path.
@@ -132,12 +152,12 @@ module Merb::Template
 
   class Erubis    
     # ==== Parameters
-    # path&lt;String&gt;:: A full path to the template.
+    # io&lt;#path&gt;:: An IO containing the full path of the template.
     # name&lt;String&gt;:: The name of the method that will be created.
     # mod&lt;Module&gt;:: The module that the compiled method will be placed into.
-    def self.compile_template(path, name, mod)
-      template = ::Erubis::Eruby.new(File.read(path))
-      template.def_method(mod, name, path) 
+    def self.compile_template(io, name, mod)
+      template = ::Erubis::Eruby.new(io.read)
+      template.def_method(mod, name, File.expand_path(io.path))
       name
     end
 </diff>
      <filename>lib/merb-core/controller/template.rb</filename>
    </modified>
    <modified>
      <diff>@@ -10,4 +10,4 @@ require corelib/:object
 require corelib/:object_space
 require corelib/:rubygems
 require corelib/:set
-
+require corelib/:virtual_file</diff>
      <filename>lib/merb-core/core_ext.rb</filename>
    </modified>
    <modified>
      <diff>@@ -30,6 +30,12 @@ class Class
   # Defines class-level and instance-level attribute reader.
   #
   # @param *syms&lt;Array&gt; Array of attributes to define reader for.
+  # @return &lt;Array[#to_s]&gt; List of attributes that were made into cattr_readers
+  #
+  # @api public
+  #
+  # @todo Is this inconsistent in that it does not allow you to prevent
+  #   an instance_reader via :instance_reader =&gt; false
   def cattr_reader(*syms)
     syms.flatten.each do |sym|
       next if sym.is_a?(Hash)
@@ -51,13 +57,15 @@ class Class
 
   # Defines class-level (and optionally instance-level) attribute writer.
   #
-  # @param *syms&lt;Array&gt; Array of attributes to define writer for.
+  # @param &lt;Array[*#to_s, Hash{:instance_writer =&gt; Boolean}]&gt; Array of attributes to define writer for.
+  # @option syms :instance_writer&lt;Boolean&gt; if true, instance-level attribute writer is defined.
+  # @return &lt;Array[#to_s]&gt; List of attributes that were made into cattr_writers
   #
-  # @option * :instance_writer&lt;Boolean&gt; if true, instance-level attribute writer is defined.
+  # @api public
   def cattr_writer(*syms)
     options = syms.last.is_a?(Hash) ? syms.pop : {}
     syms.flatten.each do |sym|
-      class_eval(&lt;&lt;-EOS, __FILE__, __LINE__)
+      class_eval(&lt;&lt;-RUBY, __FILE__, __LINE__)
         unless defined? @@#{sym}
           @@#{sym} = nil
         end
@@ -65,22 +73,25 @@ class Class
         def self.#{sym}=(obj)
           @@#{sym} = obj
         end
-
-        #{&quot;
-
-        def #{sym}=(obj)
-          @@#{sym} = obj
-        end
-        &quot; unless options[:instance_writer] == false }
-      EOS
+      RUBY
+      
+      unless options[:instance_writer] == false
+        class_eval(&lt;&lt;-RUBY, __FILE__, __LINE__)
+          def #{sym}=(obj)
+            @@#{sym} = obj
+          end
+        RUBY
+      end
     end
   end
 
   # Defines class-level (and optionally instance-level) attribute accessor.
   #
-  # @param *syms&lt;Array&gt; Array of attributes to define accessor for.
+  # @param *syms&lt;Array[*#to_s, Hash{:instance_writer =&gt; Boolean}]&gt; Array of attributes to define accessor for.
+  # @option syms :instance_writer&lt;Boolean&gt; if true, instance-level attribute writer is defined.
+  # @return &lt;Array[#to_s]&gt; List of attributes that were made into accessors
   #
-  # @option * :instance_writer&lt;Boolean&gt; if true, instance-level attribute writer is defined.
+  # @api public
   def cattr_accessor(*syms)
     cattr_reader(*syms)
     cattr_writer(*syms)
@@ -89,7 +100,16 @@ class Class
   # Defines class-level inheritable attribute reader. Attributes are available to subclasses,
   # each subclass has a copy of parent's attribute.
   #
-  # @param *syms&lt;Array&gt; Array of attributes to define inheritable reader for.
+  # @param *syms&lt;Array[#to_s]&gt; Array of attributes to define inheritable reader for.
+  # @return &lt;Array[#to_s]&gt; Array of attributes converted into inheritable_readers.
+  #
+  # @api public
+  #
+  # @todo Do we want to block instance_reader via :instance_reader =&gt; false
+  # @todo It would be preferable that we do something with a Hash passed in
+  #   (error out or do the same as other methods above) instead of silently
+  #   moving on). In particular, this makes the return value of this function
+  #   less useful.
   def class_inheritable_reader(*syms)
     syms.each do |sym|
       next if sym.is_a?(Hash)
@@ -109,25 +129,30 @@ class Class
   # Defines class-level inheritable attribute writer. Attributes are available to subclasses,
   # each subclass has a copy of parent's attribute.
   #
-  # @param *syms&lt;Array&gt; Array of attributes to define inheritable writer for.
+  # @param *syms&lt;Array[*#to_s, Hash{:instance_writer =&gt; Boolean}]&gt; Array of attributes to
+  #   define inheritable writer for.
+  # @option syms :instance_writer&lt;Boolean&gt; if true, instance-level inheritable attribute writer is defined.
+  # @return &lt;Array[#to_s]&gt; An Array of the attributes that were made into inheritable writers.
+  #
+  # @api public
   #
-  # @option * :instance_writer&lt;Boolean&gt; if true, instance-level inheritable attribute writer is defined.
+  # @todo We need a style for class_eval &lt;&lt;-HEREDOC. I'd like to make it 
+  #   class_eval(&lt;&lt;-RUBY, __FILE__, __LINE__), but we should codify it somewhere.
   def class_inheritable_writer(*syms)
     options = syms.last.is_a?(Hash) ? syms.pop : {}
     syms.each do |sym|
-      class_eval &lt;&lt;-EOS, __FILE__, __LINE__
-
+      class_eval(&lt;&lt;-RUBY, __FILE__, __LINE__)
         def self.#{sym}=(obj)
           write_inheritable_attribute(:#{sym}, obj)
         end
-
-        #{&quot;
-
-        def #{sym}=(obj)
-          self.class.#{sym} = obj
-        end
-        &quot; unless options[:instance_writer] == false }
-      EOS
+      RUBY
+      unless options[:instance_writer] == false
+        class_eval &lt;&lt;-RUBY, __FILE__, __LINE__
+          def #{sym}=(obj)
+            self.class.#{sym} = obj
+          end
+        RUBY
+      end
     end
   end
 
@@ -135,26 +160,29 @@ class Class
   # each subclass has a copy of parent's array. Difference between other inheritable
   # attributes is that array is recreated every time it is written.
   #
-  # @param *syms&lt;Array&gt; Array of array attribute names to define inheritable writer for.
-  #
-  # @option * :instance_writer&lt;Boolean&gt; if true, instance-level inheritable array 
+  # @param *syms&lt;Array[*#to_s, Hash{:instance_writer =&gt; Boolean}]&gt; Array of array attribute 
+  #   names to define inheritable writer for.
+  # @option syms :instance_writer&lt;Boolean&gt; if true, instance-level inheritable array 
   #   attribute writer is defined.
+  # @return &lt;Array[#to_s]&gt; An array of the attributes that were made into inheritable
+  #   array writers.
+  # 
+  # @api public
   def class_inheritable_array_writer(*syms)
     options = syms.last.is_a?(Hash) ? syms.pop : {}
     syms.each do |sym|
-      class_eval &lt;&lt;-EOS, __FILE__, __LINE__
-
+      class_eval(&lt;&lt;-RUBY, __FILE__, __LINE__)
         def self.#{sym}=(obj)
           write_inheritable_array(:#{sym}, obj)
         end
-
-        #{&quot;
-
-        def #{sym}=(obj)
-          self.class.#{sym} = obj
-        end
-        &quot; unless options[:instance_writer] == false }
-      EOS
+      RUBY
+      unless options[:instance_writer] == false
+        class_eval(&lt;&lt;-RUBY, __FILE__, __LINE__)
+          def #{sym}=(obj)
+            self.class.#{sym} = obj
+          end
+        RUBY
+      end
     end
   end
 
@@ -162,35 +190,40 @@ class Class
   # each subclass has a copy of parent's hash. Difference between other inheritable
   # attributes is that hash is recreated every time it is written.
   #
-  # @param *syms&lt;Array&gt;:: Array of hash attribute names to define inheritable writer for.
-  #
-  # @option * :instance_writer&lt;Boolean&gt;:: if true, instance-level inheritable hash
+  # @param *syms&lt;Array[*#to_s, Hash{:instance_writer =&gt; Boolean}]&gt;:: Array of hash 
+  #   attribute names to define inheritable writer for.
+  # @option syms :instance_writer&lt;Boolean&gt;:: if true, instance-level inheritable hash
   #   attribute writer is defined.
+  # @return &lt;Array[#to_s]&gt; An Array of attributes turned into hash_writers.
+  #
+  # @api public
   def class_inheritable_hash_writer(*syms)
     options = syms.last.is_a?(Hash) ? syms.pop : {}
     syms.each do |sym|
-      class_eval &lt;&lt;-EOS, __FILE__, __LINE__
-
+      class_eval(&lt;&lt;-RUBY, __FILE__, __LINE__)
         def self.#{sym}=(obj)
           write_inheritable_hash(:#{sym}, obj)
         end
-
-        #{&quot;
-
-        def #{sym}=(obj)
-          self.class.#{sym} = obj
-        end
-        &quot; unless options[:instance_writer] == false }
-      EOS
+      RUBY
+      unless options[:instance_writer] == false
+        class_eval(&lt;&lt;-RUBY, __FILE__, __LINE__)
+          def #{sym}=(obj)
+            self.class.#{sym} = obj
+          end
+        RUBY
+      end
     end
   end
 
   # Defines class-level inheritable attribute accessor. Attributes are available to subclasses,
   # each subclass has a copy of parent's attribute.
   #
-  # @param *syms&lt;Array&gt; Array of attributes to define inheritable accessor for.
+  # @param *syms&lt;Array[*#to_s, Hash{:instance_writer =&gt; Boolean}]&gt; Array of attributes to 
+  #   define inheritable accessor for.
+  # @option syms :instance_writer&lt;Boolean&gt; if true, instance-level inheritable attribute writer is defined.
+  # @return &lt;Array[#to_s]&gt; An Array of attributes turned into inheritable accessors.
   #
-  # @option * :instance_writer&lt;Boolean&gt; if true, instance-level inheritable attribute writer is defined.
+  # @api public
   def class_inheritable_accessor(*syms)
     class_inheritable_reader(*syms)
     class_inheritable_writer(*syms)
@@ -200,10 +233,13 @@ class Class
   # each subclass has a copy of parent's array. Difference between other inheritable
   # attributes is that array is recreated every time it is written.
   #
-  # @param *syms&lt;Array&gt; Array of array attribute names to define inheritable accessor for.
-  #
-  # @option * :instance_writer&lt;Boolean&gt; if true, instance-level inheritable array
+  # @param *syms&lt;Array[*#to_s, Hash{:instance_writer =&gt; Boolean}]&gt; Array of array attribute 
+  #   names to define inheritable accessor for.
+  # @option syms :instance_writer&lt;Boolean&gt; if true, instance-level inheritable array
   #   attribute writer is defined.
+  # @return &lt;Array[#to_s]&gt; An Array of attributes turned into inheritable arrays.
+  # 
+  # @api public
   def class_inheritable_array(*syms)
     class_inheritable_reader(*syms)
     class_inheritable_array_writer(*syms)
@@ -213,23 +249,30 @@ class Class
   # each subclass has a copy of parent's hash. Difference between other inheritable
   # attributes is that hash is recreated every time it is written.
   #
-  # @param *syms&lt;Array&gt; Array of hash attribute names to define inheritable accessor for.
-  #
-  # @option * :instance_writer&lt;Boolean&gt; if true, instance-level inheritable hash attribute writer is defined.
+  # @param *syms&lt;Array[*#to_s, Hash{:instance_writer =&gt; Boolean}]&gt; Array of hash attribute 
+  #   names to define inheritable accessor for.
+  # @option syms :instance_writer&lt;Boolean&gt; if true, instance-level inheritable hash 
+  #   attribute writer is defined.
+  # @return &lt;Array[#to_s]&gt; An Array of attributes turned into inheritable hashes.
   def class_inheritable_hash(*syms)
     class_inheritable_reader(*syms)
     class_inheritable_hash_writer(*syms)
   end
 
   # @return &lt;Hash&gt; inheritable attributes hash or it's default value, new frozen Hash.
+  # 
+  # @api private
   def inheritable_attributes
     @inheritable_attributes ||= EMPTY_INHERITABLE_ATTRIBUTES
   end
 
   # Sets the attribute which copy is available to subclasses.
   #
-  # @param key&lt;#to_s, String, Symbol&gt; inheritable attribute name
+  # @param key&lt;#to_s&gt; inheritable attribute name
   # @param value&lt;not(Array, Hash)&gt; value of inheritable attribute
+  # @return &lt;not(Array, Hash)&gt; the value that was set
+  #
+  # @api private
   #
   # @note
   #   If inheritable attributes storage has it's default value,
@@ -243,8 +286,11 @@ class Class
 
   # Sets the array attribute which copy is available to subclasses.
   #
-  # @param key&lt;#to_s, String, Symbol&gt; inheritable attribute name
-  # value&lt;Array&gt; value of inheritable attribute
+  # @param key&lt;#to_s&gt; inheritable attribute name
+  # @param elements&lt;Array&gt; value of inheritable attribute
+  # @return &lt;Array&gt; the Array that was set
+  #
+  # @api private
   #
   # @note
   #   Inheritable array is re-created on each write.
@@ -255,8 +301,12 @@ class Class
 
   # Sets the hash attribute which copy is available to subclasses.
   #
-  # @param key&lt;#to_s, String, Symbol&gt; inheritable attribute name
+  # @param key&lt;#to_s&gt; inheritable attribute name
   # @param value&lt;Hash&gt; value of inheritable attribute
+  # @return &lt;Hash&gt; the new hash that resulted from merging the new values
+  #   with the inherited values.
+  #
+  # @api private
   #
   # @note
   #   Inheritable hash is re-created on each write.
@@ -267,14 +317,24 @@ class Class
 
   # Reads value of inheritable attributes.
   #
+  # @param key&lt;#to_s&gt; the key of the attribute to read
   # @return &lt;Object&gt; 
   #   Inheritable attribute value. Subclasses store copies of values.
+  #
+  # @api private
   def read_inheritable_attribute(key)
     inheritable_attributes[key]
   end
 
-  # Resets inheritable attributes to either EMPTY_INHERITABLE_ATTRIBUTES
-  # if it is defined or it's default value, new frozen Hash.
+  # Resets inheritable attributes.
+  #
+  # @return &lt;Object&gt; the empty inheritable attributes. By default, this
+  #   is a frozen, empty Hash. You can override this for a class by defining
+  #   EMPTY_INHERITABLE_ATTRIBUTES
+  #
+  # @api private
+  #
+  # @todo do we need this?
   def reset_inheritable_attributes
     @inheritable_attributes = EMPTY_INHERITABLE_ATTRIBUTES
   end
@@ -283,6 +343,7 @@ class Class
     # Prevent this constant from being created multiple times
     EMPTY_INHERITABLE_ATTRIBUTES = {}.freeze unless const_defined?(:EMPTY_INHERITABLE_ATTRIBUTES)
 
+    # @todo document this
     def inherited_with_inheritable_attributes(child)
       inherited_without_inheritable_attributes(child) if respond_to?(:inherited_without_inheritable_attributes)
 </diff>
      <filename>lib/merb-core/core_ext/class.rb</filename>
    </modified>
    <modified>
      <diff>@@ -126,7 +126,9 @@ class Hash
   #   { :one =&gt; 1, :two =&gt; 2, :three =&gt; 3 }.only(:one)
   #     #=&gt; { :one =&gt; 1 }
   def only(*allowed)
-    reject { |k,v| !allowed.include?(k) }
+    hash = {}
+    allowed.each {|k| hash[k] = self[k] if self.has_key?(k) }
+    hash
   end
 
   # @param *rejected&lt;Array[(String, Symbol)] The hash keys to exclude.
@@ -137,7 +139,9 @@ class Hash
   #   { :one =&gt; 1, :two =&gt; 2, :three =&gt; 3 }.except(:one)
   #     #=&gt; { :two =&gt; 2, :three =&gt; 3 }
   def except(*rejected)
-    reject { |k,v| rejected.include?(k) }
+    hash = self.dup
+    rejected.each {|k| hash.delete(k) }
+    hash
   end
 
   # @return &lt;String&gt; The hash as attributes for an XML tag.</diff>
      <filename>lib/merb-core/core_ext/hash.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,12 +1,26 @@
 module Kernel
-  # Loads the given string as a gem. Execution is deferred to
-  # the Merb::BootLoader::Dependencies.run during bootup.
-  #
+  # Loads the given string as a gem. Execution is deferred until
+  # after the logger has been instantiated and the framework directory
+  # structure is defined.
+  #
+  # If that has already happened, the gem will be activated
+  # immediately.
+  # 
+  # ==== Parameters
   # @param name&lt;String&gt; The name of the gem to load.
   # @param *ver&lt;Gem::Requirement, Gem::Version, Array, #to_str&gt;
   #   Version requirements to be passed to Gem.activate.
+  #
+  # ==== Returns
+  # Array[String, Array[Gem::Requirement, Gem::Version, Array, #to_str]]::
+  #   The name and version information that was passed in.
   def dependency(name, *ver)
-    Merb::BootLoader::Dependencies.dependencies &lt;&lt; [name, ver]
+    if Merb::BootLoader.finished?(Merb::BootLoader::Dependencies)
+      load_dependency(name, *ver)
+    else
+      Merb::BootLoader::Dependencies.dependencies &lt;&lt; [name, ver]
+    end
+    [name, ver]
   end
 
   # Loads the given string as a gem.</diff>
      <filename>lib/merb-core/core_ext/kernel.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,3 +1,5 @@
+require 'tempfile'
+
 module Merb
   
   class Request
@@ -12,12 +14,14 @@ module Merb
     self.parse_json_params = true
     self.parse_xml_params = true
     
-    # Most web browsers can't send PUT or DELETE requests
-    # Any Strings stored in this array will be used as paramaters
-    # to find the real method.  Common examples are _method and
-    # fb_sig_request_method 
-    cattr_accessor :browser_method_workarounds
-    self.browser_method_workarounds = []
+    # Flash, and some older browsers can't use arbitrary
+    # request methods -- i.e., are limited to GET/POST.
+    # These user-agents can make POST requests in combination
+    # with these overrides to participate fully in REST
+    # Common examples are _method or fb_sig_request_method
+    # in the params, or an X-HTTP-Method-Override header
+    cattr_accessor :http_method_overrides
+    self.http_method_overrides = []
     
     # Initial the request object.
     #
@@ -36,9 +40,10 @@ module Merb
     # Symbol:: The name of the request method, e.g. :get.
     #
     # ==== Notes
-    # If the method is post, then the params specified in
-    # browser_method_workarounds will be checked for the masquerading method.
-    # The first matching workaround wins.
+    # If the method is post, then the blocks specified in
+    # http_method_overrides will be checked for the masquerading method.
+    # The block will get the controller yielded to it.  The first matching workaround wins.
+    # To disable this behavior, set http_method_overrides = []
     def method
       @method ||= begin
         request_method = @env['REQUEST_METHOD'].downcase.to_sym
@@ -46,17 +51,9 @@ module Merb
         when :get, :head, :put, :delete
           request_method
         when :post
-          if self.class.parse_multipart_params
-            p = body_and_query_params.merge(multipart_params)
-          else  
-            p = body_and_query_params
-          end
           m = nil
-          self.class.browser_method_workarounds.each do |workaround|
-            if p.include?(workaround.to_s)
-              m = p[workaround.to_s]
-              break
-            end
+          self.class.http_method_overrides.each do |o|
+            m ||= o.call(self); break if m
           end
           m.downcase! if m
           METHODS.include?(m) ? m.to_sym : :post
@@ -115,9 +112,9 @@ module Merb
     def multipart_params
       @multipart_params ||= 
         begin
-          # if the content-type is multipart and there's stuff in the body,
+          # if the content-type is multipart
           # parse the multipart. Otherwise return {}
-          if (Merb::Const::MULTIPART_REGEXP =~ content_type &amp;&amp; @body.size &gt; 0)
+          if (Merb::Const::MULTIPART_REGEXP =~ content_type)
             self.class.parse_multipart(@body, $1, content_length)
           else
             {}
@@ -396,7 +393,7 @@ module Merb
     class &lt;&lt; self
       
       # ==== Parameters
-      # value&lt;Array, Hash, ~to_s&gt;:: The value for the query string.
+      # value&lt;Array, Hash, Dictionary ~to_s&gt;:: The value for the query string.
       # prefix&lt;~to_s&gt;:: The prefix to add to the query string keys.
       #
       # ==== Returns
@@ -420,7 +417,7 @@ module Merb
           value.map { |v|
             params_to_query_string(v, &quot;#{prefix}[]&quot;)
           } * &quot;&amp;&quot;
-        when Hash
+        when Hash, Dictionary
           value.map { |k, v|
             params_to_query_string(v, prefix ? &quot;#{prefix}[#{Merb::Request.escape(k)}]&quot; : Merb::Request.escape(k))
           } * &quot;&amp;&quot;
@@ -454,18 +451,21 @@ module Merb
       # ==== Parameters
       # qs&lt;String&gt;:: The query string.
       # d&lt;String&gt;:: The query string divider. Defaults to &quot;&amp;&quot;.
+      # preserve_order&lt;Boolean&gt;:: Preserve order of args. Defaults to false.
       #
       # ==== Returns
-      # Mash:: The parsed query string.
+      # Mash:: The parsed query string (Dictionary if preserve_order is set).
       #
       # ==== Examples
       #   query_parse(&quot;bar=nik&amp;post[body]=heya&quot;)
       #     # =&gt; { :bar =&gt; &quot;nik&quot;, :post =&gt; { :body =&gt; &quot;heya&quot; } }
-      def query_parse(qs, d = '&amp;;')
-        (qs||'').split(/[#{d}] */n).inject({}) { |h,p| 
+      def query_parse(qs, d = '&amp;;', preserve_order = false)
+        qh = preserve_order ? Dictionary.new : {}
+        (qs||'').split(/[#{d}] */n).inject(qh) { |h,p| 
           key, value = unescape(p).split('=',2)
           normalize_params(h, key, value)
-        }.to_mash
+        }
+        preserve_order ? qh : qh.to_mash
       end
     
       NAME_REGEX = /Content-Disposition:.* name=&quot;?([^\&quot;;]*)&quot;?/ni.freeze
@@ -494,6 +494,7 @@ module Merb
         bufsize = 16384
         content_length -= boundary_size
         status = input.read(boundary_size)
+        return {} if status == nil || status.empty?
         raise ControllerExceptions::MultiPartParseError, &quot;bad content body:\n'#{status}' should == '#{boundary + EOL}'&quot;  unless status == boundary + EOL
         rx = /(?:#{EOL})?#{Regexp.quote(boundary,'n')}(#{EOL}|--)/
         loop {</diff>
      <filename>lib/merb-core/dispatch/request.rb</filename>
    </modified>
    <modified>
      <diff>@@ -31,6 +31,11 @@ module Merb
     cattr_accessor :routes, :named_routes
 
     class &lt;&lt; self
+      
+      # Clear all routes.
+      def reset!
+        self.routes, self.named_routes = [], {}
+      end
 
       # Appends the generated routes to the current routes.
       #
@@ -66,6 +71,18 @@ module Merb
         compile
       end
 
+      # Capture any new routes that have been added within the block.
+      #
+      # This utility method lets you track routes that have been added;
+      # it doesn't affect how/which routes are added.
+      #
+      # &amp;block:: A context in which routes are generated.
+      def capture(&amp;block)
+        routes_before, named_route_keys_before = self.routes.dup, self.named_routes.keys
+        yield
+        [self.routes - routes_before, self.named_routes.except(*named_route_keys_before)]
+      end
+
       # ==== Returns
       # String:: A routing lambda statement generated from the routes.
       def compiled_statement</diff>
      <filename>lib/merb-core/dispatch/router.rb</filename>
    </modified>
    <modified>
      <diff>@@ -477,7 +477,7 @@ module Merb
       #
       # ==== Examples
       #
-      #  r.resources :account # will result in the typical RESTful CRUD
+      #  r.resource :account # will result in the typical RESTful CRUD
       #    # GET     /account/new                :action =&gt; &quot;new&quot;
       #    # POST    /account/?(\.:format)?,     :action =&gt; &quot;create&quot;
       #    # GET     /account/(\.:format)?       :action =&gt; &quot;show&quot;
@@ -635,6 +635,10 @@ module Merb
       def redirects?
         @redirects
       end
+      
+      def ancestors
+        @ancestors ||= find_ancestors
+      end
 
     protected
 
@@ -743,12 +747,12 @@ module Merb
       #
       # ==== Returns
       # Array:: All the ancestor behaviors of this behavior.
-      def ancestors(list = [])
+      def find_ancestors(list = [])
         if parent.nil?
           list
         else
           list.push parent
-          parent.ancestors list
+          parent.find_ancestors list
           list
         end
       end</diff>
      <filename>lib/merb-core/dispatch/router/behavior.rb</filename>
    </modified>
    <modified>
      <diff>@@ -132,7 +132,7 @@ module Merb
       # ==== Returns
       # String:: The route as a string, e.g. &quot;admin/:controller/:id&quot;.
       def to_s
-        segments.inject('') do |str,seg|
+        (segments || []).inject('') do |str,seg|
           str &lt;&lt; (seg.is_a?(Symbol) ? &quot;:#{seg}&quot; : seg)
         end
       end
@@ -148,7 +148,7 @@ module Merb
       # ==== Returns
       # Array:: All the symbols in the segments array.
       def symbol_segments
-        segments.select{ |s| s.is_a?(Symbol) }
+        (segments || []).select{ |s| s.is_a?(Symbol) }
       end
 
       # Turn a path into string and symbol segments so it can be reconstructed,
@@ -189,7 +189,7 @@ module Merb
       #   True if this route is a regexp, i.e. its behavior or one of the
       #   behavior's ancestors is a regexp.
       def regexp?
-        behavior.regexp? || behavior.send(:ancestors).any? { |a| a.regexp? }
+        @regexp ||= behavior.regexp? || behavior.ancestors.any? { |a| a.regexp? }
       end
 
       # Generates URL using route segments and given parameters.</diff>
      <filename>lib/merb-core/dispatch/router/route.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,16 @@
 module Merb
   
   module SessionMixin
+    # Sets the session id cookie, along with the correct
+    # expiry and domain -- used for new or reset sessions
+    def set_session_id_cookie(key)
+      options = {}
+      options[:value] = key
+      options[:expires] = Time.now + _session_expiry if _session_expiry &gt; 0
+      options[:domain] = _session_cookie_domain if _session_cookie_domain
+      cookies[_session_id_key] = options
+    end
+
     @_finalize_session_exception_callbacks = []
     @_persist_exception_callbacks = []
     
@@ -43,4 +53,4 @@ module Merb
     module_function :rand_uuid, :needs_new_cookie!, :finalize_session_exception_callbacks, :persist_exception_callbacks
   end
 
-end
\ No newline at end of file
+end</diff>
      <filename>lib/merb-core/dispatch/session.rb</filename>
    </modified>
    <modified>
      <diff>@@ -8,10 +8,13 @@ module Merb
     # ==== Parameters
     # base&lt;Class&gt;:: The class to which the SessionMixin is mixed into.
     def setup_session
-      before = cookies[_session_id_key]
-      request.session, cookies[_session_id_key] = Merb::MemCacheSession.persist(cookies[_session_id_key])
+      orig_key = cookies[_session_id_key]
+      session, key = Merb::MemCacheSession.persist(orig_key)
+      request.session = session
       @_fingerprint = Marshal.dump(request.session.data).hash
-      @_new_cookie = cookies[_session_id_key] != before
+      if key != orig_key 
+        set_session_id_cookie(key)
+      end
     end
 
     # Finalizes the session by storing the session ID in a cookie, if the
@@ -25,9 +28,9 @@ module Merb
           Merb::SessionMixin::finalize_session_exception_callbacks.each {|x| x.call(err) }
         end
       end
-      options = {:expires =&gt; (Time.now + _session_expiry)}
-      options[:domain] = _session_cookie_domain if _session_cookie_domain
-      set_cookie(_session_id_key, request.session.session_id, options) if (@_new_cookie || request.session.needs_new_cookie)
+      if request.session.needs_new_cookie or @_new_cookie
+        set_session_id_cookie(request.session.session_id)
+      end
     end
 
     # ==== Returns</diff>
      <filename>lib/merb-core/dispatch/session/memcached.rb</filename>
    </modified>
    <modified>
      <diff>@@ -8,17 +8,20 @@ module Merb
     # ==== Parameters
     # base&lt;Class&gt;:: The class to which the SessionMixin is mixed into.
     def setup_session
-      before = cookies[_session_id_key]
-      request.session , cookies[_session_id_key] = Merb::MemorySession.persist(cookies[_session_id_key])
-      @_new_cookie = cookies[_session_id_key] != before
+      orig_key = cookies[_session_id_key]
+      session, key = Merb::MemorySession.persist(orig_key)
+      request.session = session
+      if key != orig_key 
+        set_session_id_cookie(key)
+      end
     end
 
     # Finalizes the session by storing the session ID in a cookie, if the
     # session has changed.
     def finalize_session
-      options = {:expires =&gt; (Time.now + _session_expiry)}
-      options[:domain] = _session_cookie_domain if _session_cookie_domain
-      set_cookie(_session_id_key, request.session.session_id, options) if (@_new_cookie || request.session.needs_new_cookie)
+      if request.session.needs_new_cookie or @_new_cookie
+        set_session_id_cookie(request.session.session_id)
+      end
     end
 
     # ==== Returns
@@ -233,4 +236,4 @@ module Merb
   end # end MemorySessionContainer
 end
 
-Merb::MemorySessionContainer.setup(Merb::Config[:memory_session_ttl])
\ No newline at end of file
+Merb::MemorySessionContainer.setup(Merb::Config[:memory_session_ttl])</diff>
      <filename>lib/merb-core/dispatch/session/memory.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,18 +1,20 @@
 require 'rack'
 module Merb  
   module Rack
-    autoload :Application,    &quot;merb-core/rack/application&quot;
-    autoload :Adapter,        &quot;merb-core/rack/adapter&quot;
-    autoload :Ebb,            &quot;merb-core/rack/adapter/ebb&quot;
-    autoload :EventedMongrel, &quot;merb-core/rack/adapter/evented_mongrel&quot;    
-    autoload :FastCGI,        &quot;merb-core/rack/adapter/fcgi&quot;
-    autoload :Irb,            &quot;merb-core/rack/adapter/irb&quot;
-    autoload :Middleware,     &quot;merb-core/rack/middleware&quot;
-    autoload :Mongrel,        &quot;merb-core/rack/adapter/mongrel&quot;
-    autoload :Runner,         &quot;merb-core/rack/adapter/runner&quot;    
-    autoload :Thin,           &quot;merb-core/rack/adapter/thin&quot;
-    autoload :WEBrick,        &quot;merb-core/rack/adapter/webrick&quot;
-    autoload :PathPrefix,     &quot;merb-core/rack/apps/path_prefix&quot;
-    autoload :Static,         &quot;merb-core/rack/apps/static&quot;
+    autoload :Application,         &quot;merb-core/rack/application&quot;
+    autoload :Adapter,             &quot;merb-core/rack/adapter&quot;
+    autoload :Ebb,                 &quot;merb-core/rack/adapter/ebb&quot;
+    autoload :EventedMongrel,      &quot;merb-core/rack/adapter/evented_mongrel&quot;    
+    autoload :FastCGI,             &quot;merb-core/rack/adapter/fcgi&quot;
+    autoload :Irb,                 &quot;merb-core/rack/adapter/irb&quot;
+    autoload :Middleware,          &quot;merb-core/rack/middleware&quot;
+    autoload :Mongrel,             &quot;merb-core/rack/adapter/mongrel&quot;
+    autoload :Runner,              &quot;merb-core/rack/adapter/runner&quot;    
+    autoload :SwiftipliedMongrel,  &quot;merb-core/rack/adapter/swiftiplied_mongrel&quot;
+    autoload :Thin,                &quot;merb-core/rack/adapter/thin&quot;
+    autoload :WEBrick,             &quot;merb-core/rack/adapter/webrick&quot;
+    autoload :PathPrefix,          &quot;merb-core/rack/middleware/path_prefix&quot;
+    autoload :Static,              &quot;merb-core/rack/middleware/static&quot;
+    autoload :Profiler,            &quot;merb-core/rack/middleware/profiler&quot;    
   end # Rack
 end # Merb
\ No newline at end of file</diff>
      <filename>lib/merb-core/rack.rb</filename>
    </modified>
    <modified>
      <diff>@@ -28,14 +28,15 @@ module Merb
     end # Adapter
     
     # Register some Rack adapters
-    Adapter.register %w{ebb},          :Ebb
-    Adapter.register %w{emongrel},     :EventedMongrel
-    Adapter.register %w{fastcgi fcgi}, :FastCGI
-    Adapter.register %w{irb},          :Irb
-    Adapter.register %w{mongrel},      :Mongrel  
-    Adapter.register %w{runner},       :Runner
-    Adapter.register %w{thin},         :Thin
-    Adapter.register %w{webrick},      :WEBrick
+    Adapter.register %w{ebb},            :Ebb
+    Adapter.register %w{emongrel},       :EventedMongrel
+    Adapter.register %w{fastcgi fcgi},   :FastCGI
+    Adapter.register %w{irb},            :Irb
+    Adapter.register %w{mongrel},        :Mongrel  
+    Adapter.register %w{runner},         :Runner
+    Adapter.register %w{smongrel swift}, :SwiftipliedMongrel
+    Adapter.register %w{thin},           :Thin
+    Adapter.register %w{webrick},        :WEBrick
     
   end # Rack
 end # Merb</diff>
      <filename>lib/merb-core/rack/adapter.rb</filename>
    </modified>
    <modified>
      <diff>@@ -99,9 +99,9 @@ module Merb
       def dispatch_to(controller_klass, action, params = {}, env = {}, &amp;blk)
         action = action.to_s
         request_body = { :post_body =&gt; env[:post_body], :req =&gt; env[:req] }
-        request = fake_request(env.merge(
-          :query_string =&gt; Merb::Request.params_to_query_string(params)), request_body)
-
+        params = Merb::Request.params_to_query_string(params)
+        env[:query_string] = env[&quot;QUERY_STRING&quot;] ? &quot;#{env[&quot;QUERY_STRING&quot;]}&amp;#{params}&quot; : params
+        request = fake_request(env, request_body)
         dispatch_request(request, controller_klass, action, &amp;blk)
       end
 
@@ -239,7 +239,8 @@ module Merb
       # @semi-public
       def request(path, params = {}, env= {}, &amp;block)
         env[:request_method] ||= &quot;GET&quot;
-        env[:request_uri] = path
+        env[:request_uri], env[:query_string] = path.split('?')
+        
         multipart = env.delete(:test_with_multipart)
 
         request = fake_request(env)</diff>
      <filename>lib/merb-core/test/helpers/request_helper.rb</filename>
    </modified>
    <modified>
      <diff>@@ -17,10 +17,12 @@ end
 
 describe Hash, &quot;only&quot; do
   before do
-    @hash = { :one =&gt; 'ONE', 'two' =&gt; 'TWO', 3 =&gt; 'THREE' }
+    @hash = { :one =&gt; 'ONE', 'two' =&gt; 'TWO', 3 =&gt; 'THREE', 4 =&gt; nil }
   end
 
   it &quot;should return a hash with only the given key(s)&quot; do
+    @hash.only(:not_in_there).should == {}
+    @hash.only(4).should == {4 =&gt; nil}
     @hash.only(:one).should == { :one =&gt; 'ONE' }
     @hash.only(:one, 3).should == { :one =&gt; 'ONE', 3 =&gt; 'THREE' }
   end</diff>
      <filename>spec/private/core_ext/hash_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -48,18 +48,6 @@ describe &quot;Kernel#debugger&quot; do
 end
 
 
-describe &quot;Kernel#dependency&quot; do
-  it &quot;adds dependency to the list&quot; do
-    lambda { dependency(&quot;dm_merb&quot;, &quot;&gt;= 0.9&quot;) }.should change(Merb::BootLoader::Dependencies.dependencies, :size)
-  end
-
-  it &quot;deferres load to boot loader run&quot; do
-    Object.should_not_receive(:full_const_get)
-    dependency(&quot;dm_merb&quot;, &quot;&gt;= 0.9&quot;)
-  end
-end
-
-
 describe &quot;Kernel#load_dependency&quot; do
   before :each do
 </diff>
      <filename>spec/private/core_ext/kernel_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -14,6 +14,10 @@ describe Merb::Router::Route, &quot;initially&quot; do
     @r5 = Merb::Router.routes[4]
   end
 
+  after :each do
+    Merb::Router.reset!
+  end
+
   it &quot;has reader for conditions&quot; do
     @r1.conditions
   end
@@ -47,7 +51,6 @@ describe Merb::Router::Route, &quot;initially&quot; do
   end
 end
 
-
 describe Merb::Router::Route, &quot;#fixatable&quot; do
   predicate_matchers[:allow_fixation] = :allow_fixation?
 
@@ -60,6 +63,10 @@ describe Merb::Router::Route, &quot;#fixatable&quot; do
 
     @route = Merb::Router.routes[4]
   end
+  
+  after :each do
+    Merb::Router.reset!
+  end
 
   it &quot;allows fixation when called with true&quot; do
     @route.fixatable(true)
@@ -94,6 +101,10 @@ describe Merb::Router::Route, &quot;#to_s&quot; do
 
     @route = Merb::Router.routes[4]
   end
+  
+  after :each do
+    Merb::Router.reset!
+  end
 
   it &quot;concatenates route segments&quot; do
     @route.stub!(:segments).and_return([&quot;continents/&quot;, &quot;new&quot;])
@@ -118,6 +129,10 @@ describe Merb::Router::Route, &quot;#register&quot; do
 
     @route = Merb::Router.routes[4]
   end
+  
+  after :each do
+    Merb::Router.reset!
+  end
 
   it &quot;adds route to Merb routes set&quot; do
     Merb::Router.routes = []
@@ -153,7 +168,7 @@ describe Merb::Router::Route, &quot;#symbol_segments&quot; do
   end
 
   after :each do
-    Merb::Router.routes = []
+    Merb::Router.reset!
   end
 
   it &quot;cherrypicks segments that are Symbols&quot; do
@@ -176,7 +191,7 @@ describe Merb::Router::Route, &quot;#segments_from_path&quot; do
   end
 
   after :each do
-    Merb::Router.routes = []
+    Merb::Router.reset!
   end
 
   it &quot;turns path into string and symbol segments&quot; do
@@ -200,7 +215,7 @@ describe Merb::Router::Route, &quot;#name&quot; do
   end
 
   after :each do
-    Merb::Router.routes = []
+    Merb::Router.reset!
   end
 
   it &quot;places the route into named routes collection&quot; do
@@ -212,10 +227,10 @@ describe Merb::Router::Route, &quot;#name&quot; do
   it &quot;only accepts Symbols&quot; do
     lambda { @route.name(&quot;home&quot;) }.should raise_error(ArgumentError)
   end
+  
 end
 
 
-
 describe Merb::Router::Route, &quot;#regexp?&quot; do
   before :each do
     Merb::Router.prepare do |r|
@@ -251,7 +266,7 @@ describe Merb::Router::Route, &quot;#regexp?&quot; do
   end
 
   after :each do
-    Merb::Router.routes = []
+    Merb::Router.reset!
   end
 end
 
@@ -267,6 +282,10 @@ describe Merb::Router::Route, &quot;#generate&quot; do
     @regexp_route   = Merb::Router.named_routes[:regexpy]
     @non_regexp_route = Merb::Router.named_routes[:non_regexpy]
   end
+  
+  after :each do
+    Merb::Router.reset!
+  end
 
   it &quot;does not work for regexp routes&quot; do
     lambda { @regexp_route.generate({ :token =&gt; &quot;apitoken&quot; }) }.should raise_error(RuntimeError, /regexp/)
@@ -304,6 +323,10 @@ describe Merb::Router::Route, &quot;#if_conditions&quot; do
     @non_regexp_route = Merb::Router.named_routes[:non_regexpy]
     @two_symbol_route = Merb::Router.named_routes[:two_symbol_segments]
   end
+  
+  after :each do
+    Merb::Router.reset!
+  end
 
   it &quot;returns array with =~ statements&quot; do
     # just to show you what it looks like
@@ -328,8 +351,6 @@ describe Merb::Router::Route, &quot;#if_conditions&quot; do
   end
 end
 
-
-
 describe Merb::Router::Route, &quot;#if_conditions&quot; do
   before :each do
     Merb::Router.prepare do |r|
@@ -342,6 +363,10 @@ describe Merb::Router::Route, &quot;#if_conditions&quot; do
     @non_regexp_route = Merb::Router.named_routes[:non_regexpy]
     @two_symbol_route = Merb::Router.named_routes[:two_symbol_segments]
   end
+  
+  after :each do
+    Merb::Router.reset!
+  end
 
   it &quot;uses if in compiled statement when argument is false&quot; do
     @regexp_route.compile(false).should =~ /\s*elsif/
@@ -355,3 +380,35 @@ describe Merb::Router::Route, &quot;#if_conditions&quot; do
     @regexp_route.compile.should =~ /\s*elsif/
   end
 end
+
+describe &quot;Merb::Router::Route.capture&quot; do
+  
+  after :each do
+    Merb::Router.reset!
+  end  
+  
+  it &quot;should capture routes that have been added in the block context&quot; do
+    routes, named, route = [], {}, nil
+    Merb::Router.prepare do |r|
+      routes, named = Merb::Router.capture do
+        route = r.match(&quot;/overview&quot;).to(:controller =&gt; &quot;home&quot;, :action =&gt; 'overview')
+      end
+      r.match(&quot;/&quot;).to(:controller =&gt; &quot;home&quot;).name(:home)
+    end
+    routes.should include(route)
+    named.should_not include(route)
+  end
+  
+  it &quot;should capture named routes that have been added in the block context&quot; do
+    routes, named, route = [], {}, nil
+    Merb::Router.prepare do |r|
+      r.match(&quot;/overview&quot;).to(:controller =&gt; &quot;home&quot;, :action =&gt; 'overview')
+      routes, named = Merb::Router.capture do
+        route = r.match(&quot;/&quot;).to(:controller =&gt; &quot;home&quot;).name(:home)
+      end
+    end
+    routes.should include(route)
+    named[:home].should == route
+  end
+  
+end</diff>
      <filename>spec/private/router/route_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -11,7 +11,7 @@ module Merb::Test::Fixtures
         &quot;partial/#{File.basename(controller)}/#{context}&quot;
       end
     end
-
+    
     class BasicPartial &lt; RenderIt
 
       def index
@@ -19,6 +19,14 @@ module Merb::Test::Fixtures
       end
     end
 
+    class WithAbsolutePartial &lt; RenderIt
+      
+      def index
+        @absolute_partial_path = File.expand_path(File.dirname(__FILE__)) / 'views' / 'partial' / 'with_absolute_partial' / 'partial'
+        render 
+      end
+    end
+
     class WithPartial &lt; RenderIt
 
       def index</diff>
      <filename>spec/public/abstract_controller/controllers/partial.rb</filename>
    </modified>
    <modified>
      <diff>@@ -76,11 +76,19 @@ module Merb::Test::Fixtures
       end
     end
     
+    class RenderTemplateAbsolutePath &lt; RenderTemplate
+      
+      def index
+        render :template =&gt; File.expand_path(self._template_root) / 'wonderful' / 'index'
+      end
+      
+    end
+    
     class RenderTemplateMultipleRoots &lt; RenderTemplate
       self._template_roots &lt;&lt; [File.dirname(__FILE__) / &quot;alt_views&quot;, :_template_location]
       
       def show
-        render :layout=&gt;false
+        render :layout =&gt; false
       end
     end
 </diff>
      <filename>spec/public/abstract_controller/controllers/render.rb</filename>
    </modified>
    <modified>
      <diff>@@ -94,4 +94,13 @@ describe Merb::AbstractController, &quot; should support before and after filters&quot; do
   it &quot;should support passing arguments to a before filter method&quot; do
     dispatch_should_make_body(&quot;TestBeforeFilterWithArguments&quot;, &quot;index action&quot;)
   end
+  
+  it &quot;should inherit before filters&quot; do
+    dispatch_should_make_body(&quot;FilterChild2&quot;, &quot;Before Limited&quot;, :limited)
+  end
+  
+  it &quot;should not get contaminated by cousins&quot; do
+    pending
+    dispatch_should_make_body(&quot;FilterChild2&quot;, &quot;Before Index&quot;)
+  end
 end
\ No newline at end of file</diff>
      <filename>spec/public/abstract_controller/filter_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -50,4 +50,8 @@ describe Merb::AbstractController, &quot; Partials&quot; do
     dispatch_should_make_body(&quot;BasicPartialWithMultipleRoots&quot;, &quot;Base Index: Alt Partial&quot;)
   end
   
+  it &quot;should render a partial using an absolute path&quot; do
+    dispatch_should_make_body(&quot;WithAbsolutePartial&quot;, &quot;Index Absolute Partial&quot;)
+  end
+  
 end
\ No newline at end of file</diff>
      <filename>spec/public/abstract_controller/partial_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -63,6 +63,10 @@ describe Merb::AbstractController, &quot; rendering templates&quot; do
     dispatch_should_make_body(&quot;RenderTemplateCustomLocation&quot;, &quot;Wonderful&quot;)
   end
   
+  it &quot;should support rendering templates from an absolute path location&quot; do
+    dispatch_should_make_body(&quot;RenderTemplateAbsolutePath&quot;, &quot;Wonderful&quot;)
+  end
+
   it &quot;should support rendering templates with multiple roots&quot; do
     dispatch_should_make_body(&quot;RenderTemplateMultipleRoots&quot;, &quot;App: Multiple&quot;)
   end</diff>
      <filename>spec/public/abstract_controller/render_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -2,6 +2,7 @@ __DIR__ = File.dirname(__FILE__)
 require File.join(__DIR__, &quot;..&quot;, &quot;..&quot;, &quot;spec_helper&quot;)
 
 require File.join(__DIR__, &quot;controllers&quot;, &quot;filters&quot;)
+require File.join(__DIR__, &quot;controllers&quot;, &quot;cousins&quot;)
 require File.join(__DIR__, &quot;controllers&quot;, &quot;render&quot;)
 require File.join(__DIR__, &quot;controllers&quot;, &quot;partial&quot;)
 require File.join(__DIR__, &quot;controllers&quot;, &quot;display&quot;)</diff>
      <filename>spec/public/abstract_controller/spec_helper.rb</filename>
    </modified>
    <modified>
      <diff>@@ -21,7 +21,16 @@ module Merb::Test::Fixtures::Controllers
     def index
       @obj = SomeModel.new
       display @obj
-    end
+    end    
+  end
+
+  class DisplayWithLayout &lt; Testing
+    provides :json
+    
+    def index
+      @obj = SomeModel.new
+      display @obj, :layout =&gt; :custom_arg
+    end    
   end
 
   class DisplayHtmlDefault &lt; Display; end
@@ -46,9 +55,16 @@ module Merb::Test::Fixtures::Controllers
     def no_layout
       render :layout =&gt; false
     end
+    
+    def absolute_without_mime
+      render :template =&gt; File.expand_path(self._template_root) / &quot;merb/test/fixtures/controllers/html_default/index&quot;
+    end
+    
+    def absolute_with_mime
+      render :template =&gt; File.expand_path(self._template_root) / &quot;merb/test/fixtures/controllers/html_default/index.html&quot;
+    end
   end
-
-
+  
   class DisplayWithTemplateArgument &lt; Display
     def index
       @obj = SomeModel.new
@@ -61,7 +77,6 @@ module Merb::Test::Fixtures::Controllers
     end
   end
 
-
   class DisplayWithStringLocation &lt; Display
     provides :json
     def index</diff>
      <filename>spec/public/controller/controllers/display.rb</filename>
    </modified>
    <modified>
      <diff>@@ -23,15 +23,28 @@ describe Merb::Controller, &quot; displaying objects based on mime type&quot; do
   it &quot;overrides layout settings with render :layout =&gt; false&quot; do
     dispatch_to(Merb::Test::Fixtures::Controllers::DisplayWithTemplate, :no_layout).body.should_not match(/Custom: Template/)
   end
+  
+  it &quot;should accept an absolute template path argument - with the mimetype extension&quot; do
+    dispatch_to(Merb::Test::Fixtures::Controllers::DisplayWithTemplate, :absolute_with_mime).body.should == &quot;Custom: HTML: Default&quot;
+  end
+  
+  it &quot;should accept an absolute template path argument - without the mimetype extension&quot; do
+    dispatch_to(Merb::Test::Fixtures::Controllers::DisplayWithTemplate, :absolute_without_mime).body.should == &quot;Custom: HTML: Default&quot;
+  end
 
-  it &quot;should accept a layout argument&quot; do
+  it &quot;should accept a layout argument when calling to_*&quot; do
+    dispatch_to(Merb::Test::Fixtures::Controllers::DisplayWithLayout, :index, {}, 
+      :http_accept =&gt; &quot;application/json&quot;).body.should == &quot;{custom_arg: { 'include': '', 'exclude': '' }}&quot;
+  end
+  
+  it &quot;should accept a layout argument with a template&quot; do
     dispatch_to(Merb::Test::Fixtures::Controllers::DisplayWithTemplateArgument, :index).body.should == &quot;Custom Arg: Template&quot;
   end
 
   it &quot;should accept a template path argument&quot; do
     dispatch_to(Merb::Test::Fixtures::Controllers::DisplayWithTemplateArgument, :index_by_arg).body.should == &quot;Template&quot;
   end
-
+  
   it &quot;should use other mime-types if they are provided on the class level&quot; do
     controller = dispatch_to(Merb::Test::Fixtures::Controllers::DisplayClassProvides, :index, {}, :http_accept =&gt; &quot;application/xml&quot;)
     controller.body.should == &quot;&lt;XML:Model /&gt;&quot;</diff>
      <filename>spec/public/controller/display_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -12,4 +12,30 @@ describe Merb::Request do
     request.params[:file][:tempfile].class.should == Tempfile
     request.params[:file][:content_type].should == 'text/plain'
   end
+  
+  it &quot;should accept env['rack.input'] as IO object (instead of StringIO)&quot; do
+    file = Struct.new(:read, :filename, :path).
+      new(&quot;This is a text file with some small content in it.&quot;, &quot;sample.txt&quot;, &quot;sample.txt&quot;)
+    m = Merb::Test::MultipartRequestHelper::Post.new :file =&gt; file
+    body, head = m.to_multipart
+    
+    t = Tempfile.new(&quot;io&quot;)
+    t.write(body)
+    t.close
+    
+    fd = IO.sysopen(t.path)
+    io = IO.for_fd(fd,&quot;r&quot;)
+    request = Merb::Test::RequestHelper::FakeRequest.new({:request_method =&gt; &quot;POST&quot;, :content_type =&gt; 'multipart/form-data, boundary=----------0xKhTmLbOuNdArY', :content_length =&gt; body.length},io)
+
+    running {request.params}.should_not raise_error        
+    request.params[:file].should_not be_nil
+    request.params[:file][:tempfile].class.should == Tempfile
+    request.params[:file][:content_type].should == 'text/plain'
+  end    
+    
+  it &quot;should handle GET with a content_type but an empty body (happens in some browsers such as safari after redirect)&quot; do
+      request = fake_request({:request_method =&gt; &quot;GET&quot;, :content_type =&gt; 'multipart/form-data, boundary=----------0xKhTmLbOuNdArY', :content_length =&gt; 0}, :req =&gt; '')      
+      running {request.params}.should_not raise_error        
+  end
+  
 end
\ No newline at end of file</diff>
      <filename>spec/public/request/multipart_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -23,11 +23,11 @@ module Merb::Test::Fixtures
   
   class MyTemplateEngine
     
-    def self.compile_template(path, name, mod)
-      text = File.read(path)
+    def self.compile_template(io, name, mod)
+      text = io.read
       table = { &quot;\r&quot;=&gt;&quot;\\r&quot;, &quot;\n&quot;=&gt;&quot;\\n&quot;, &quot;\t&quot;=&gt;&quot;\\t&quot;, '&quot;'=&gt;'\\&quot;', &quot;\\&quot;=&gt;&quot;\\\\&quot; }      
       text = (text.split(&quot;\n&quot;).map {|x| '&quot;' + (x.gsub(/[\r\n\t&quot;\\]/) { |m| table[m] }) + '&quot;'}).join(&quot; +\n&quot;)
-      mod.class_eval &lt;&lt;-EOS, path
+      mod.class_eval &lt;&lt;-EOS, File.expand_path(io.path)
         def #{name}
           #{text}
         end
@@ -58,7 +58,7 @@ describe Merb::Template do
   # @semipublic
   
   def rendering_template(template_path)
-    Merb::Template.inline_template(template_path, Merb::Test::Fixtures::MyHelpers)
+    Merb::Template.inline_template(File.open(template_path), Merb::Test::Fixtures::MyHelpers)
     Merb::Test::Fixtures::Environment.new.
       send(Merb::Template.template_name(template_path))  
   end
@@ -74,6 +74,17 @@ describe Merb::Template do
     rendering_template(template_path).should == &quot;Hello world!&quot;
   end
   
+  it &quot;should compile and inline templates that comes through via VirtualFile&quot; do
+    Merb::Template.inline_template(VirtualFile.new(&quot;Hello&quot;, 
+      File.dirname(__FILE__) / &quot;templates&quot; / &quot;template.html.erb&quot;), 
+      Merb::Test::Fixtures::MyHelpers)
+      
+    res = Merb::Test::Fixtures::Environment.new.
+      send(Merb::Template.template_name(File.dirname(__FILE__) / &quot;templates&quot; / &quot;template.html.erb&quot;))
+      
+    res.should == &quot;Hello&quot;
+  end
+  
   it &quot;should know how to correctly report errors&quot; do
     template_path = File.dirname(__FILE__) / &quot;templates&quot; / &quot;error.html.erb&quot;
     running { render_template(template_path) }.should raise_error(NameError, /`foo'/)
@@ -86,7 +97,7 @@ describe Merb::Template do
   
   it &quot;should find the full template name for a path via #template_for&quot; do
     template_path = File.dirname(__FILE__) / &quot;templates&quot; / &quot;template.html.erb&quot;
-    name = Merb::Template.inline_template(template_path, Merb::Test::Fixtures::MyHelpers)
+    name = Merb::Template.inline_template(File.open(template_path), Merb::Test::Fixtures::MyHelpers)
     Merb::Test::Fixtures::Environment.new.should respond_to(name)
   end
   </diff>
      <filename>spec/public/template/template_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -26,6 +26,15 @@ describe Merb::Test::RequestHelper do
       controller.params[:name].should == &quot;Fred&quot;
     end
 
+    it &quot;should dispatch to the given controller and action with the query string merged into the params&quot; do
+      Merb::Test::ControllerAssertionMock.should_receive(:called).with(:show)
+      controller = dispatch_to(@controller_klass, :show, {:name =&gt; &quot;Fred&quot;}, {'QUERY_STRING' =&gt; &quot;last_name=Jones&amp;age=42&quot;} )
+      
+      controller.params[:name].should == &quot;Fred&quot;
+      controller.params[:last_name].should == &quot;Jones&quot;
+      controller.params[:age].should == &quot;42&quot;   
+    end
+
     it &quot;should not hit the router to match its route&quot; do
       Merb::Router.should_not_receive(:match)
       dispatch_to(@controller_klass, :index)
@@ -85,6 +94,14 @@ describe Merb::Test::RequestHelper do
       controller = get(&quot;/spec_helper_controller&quot;, :name =&gt; &quot;Harry&quot;)
       controller.params[:name].should == &quot;Harry&quot;    
     end
+    
+    it &quot;should perform the index action and have params available from the query string&quot; do
+      Merb::Test::ControllerAssertionMock.should_receive(:called).with(:index)
+      controller = get(&quot;/spec_helper_controller?last_name=Oswald&amp;age=25&quot;, :name =&gt; &quot;Harry&quot;)
+      controller.params[:name].should == &quot;Harry&quot;
+      controller.params[:last_name].should == &quot;Oswald&quot;
+      controller.params[:age].should == &quot;25&quot;
+    end
 
     it &quot;should evaluate in the context of the controller in the block&quot; do
       get(&quot;/spec_helper_controller&quot;) do |controller|</diff>
      <filename>spec/public/test/request_helper_spec.rb</filename>
    </modified>
  </modified>
  <removed type="array">
    <removed>
      <filename>deps/rack/lib/rack.rbc</filename>
    </removed>
    <removed>
      <filename>deps/rack/lib/rack/builder.rbc</filename>
    </removed>
    <removed>
      <filename>lib/merb-core/rack/apps/path_prefix.rb</filename>
    </removed>
    <removed>
      <filename>lib/merb-core/rack/apps/static.rb</filename>
    </removed>
  </removed>
  <parents type="array">
    <parent>
      <id>9238c0a2d1cce49beafb165bab8ad6513821b83e</id>
    </parent>
    <parent>
      <id>8ceb03e11d386feadfa9dd47b57d72c99e36ee6a</id>
    </parent>
  </parents>
  <author>
    <name>Michael D. Ivey</name>
    <email>ivey@gweezlebur.com</email>
  </author>
  <url>http://github.com/wycats/merb-core/commit/6155eae38811b4a8676530786fdedf48ba46cdea</url>
  <id>6155eae38811b4a8676530786fdedf48ba46cdea</id>
  <committed-date>2008-06-20T12:51:37-07:00</committed-date>
  <authored-date>2008-06-20T12:51:37-07:00</authored-date>
  <message>Merge branch 'master' of git@github.com:wycats/merb-core

* 'master' of git@github.com:wycats/merb-core: (50 commits)
  add Merb::Rack::Profiler middleware. to use add the following to your config/rack.rb file:
  update license
  Missing require
  require 'stringio'
  Add support for non-standard template reloading. Plugin authors need to override load_template_io to handle special reloading logic.
  Add support for IO templates instead of just paths. See PLUGIN_API_CHANGELOG for details.
  add swiftiplied mongrel rack adapter.
  Swapped the order of helper and controller in the default_framework
  Why should capture be private?
  Merb::Config[:framework] now needs absolute paths to work (breaks BC)
  Merb::Config[:framework] paths now pickup files using glob **/*.rb unless specified otherwise
  Don't automatically use Facebook signature
  Fixes failing spec.
  make the default rake task 'specs' so running rake in merb-core just runs the specs
  Rename @status to @_status
  Avoid adding nil values in place of missing keys for Hash#only
  Fix issue with null segments
  Fixed session cookie expires value [#366 state:resolved]
  Made HTTP method override proc-based and pluggable. [#364]
  siiiiiigh.
  ...</message>
  <tree>cce28fdf0484ff88c3acf36df2e9e9f552dd8637</tree>
  <committer>
    <name>Michael D. Ivey</name>
    <email>ivey@gweezlebur.com</email>
  </committer>
</commit>
