Skip to content

Commit

Permalink
More perf work:
Browse files Browse the repository at this point in the history
  * Move #set_cookie and #delete_cookie inline to optimize. These optimizations should
    almost certainly be sent back upstream to Rack. The optimization involves using
    an ivar for cookies instead of indexing into the headers each time.
  * Was able to use a bare Hash for headers now that cookies have their own joining
    semantics (some code assumed that the raw cookies were an Array).
  * Cache blankness of body on body=
  * Improve expand_cache_key for Arrays of a single element (common in our case)
  * Use a simple layout condition check unless conditions are used
  * Cache visible actions
  * Lazily load the UrlRewriter
  * Make etag an ivar that is set on prepare!
  • Loading branch information
wycats committed Aug 11, 2009
1 parent 0adbeeb commit 4bf516e
Show file tree
Hide file tree
Showing 11 changed files with 128 additions and 100 deletions.
49 changes: 32 additions & 17 deletions actionpack/lib/abstract_controller/layouts.rb
Expand Up @@ -6,17 +6,21 @@ module Layouts

included do
extlib_inheritable_accessor(:_layout_conditions) { Hash.new }
extlib_inheritable_accessor(:_action_has_layout) { Hash.new }
_write_layout_method
end

module ClassMethods
def inherited(klass)
super
klass._write_layout_method
klass.class_eval do
_write_layout_method
@found_layouts = {}
end
end

def cache_layout(details)
layout = @found_layouts ||= {}
layout = @found_layouts
values = details.values_at(:formats, :locale)

# Cache nil
Expand All @@ -27,6 +31,28 @@ def cache_layout(details)
end
end

# This module is mixed in if layout conditions are provided. This means
# that if no layout conditions are used, this method is not used
module LayoutConditions
# Determines whether the current action has a layout by checking the
# action name against the :only and :except conditions set on the
# layout.
#
# ==== Returns
# Boolean:: True if the action has a layout, false otherwise.
def _action_has_layout?
conditions = _layout_conditions

if only = conditions[:only]
only.include?(action_name)
elsif except = conditions[:except]
!except.include?(action_name)
else
true
end
end
end

# Specify the layout to use for this class.
#
# If the specified layout is a:
Expand All @@ -43,6 +69,8 @@ def cache_layout(details)
# :only<#to_s, Array[#to_s]>:: A list of actions to apply this layout to.
# :except<#to_s, Array[#to_s]>:: Apply this layout to all actions but this one
def layout(layout, conditions = {})
include LayoutConditions unless conditions.empty?

conditions.each {|k, v| conditions[k] = Array(v).map {|a| a.to_s} }
self._layout_conditions = conditions

Expand Down Expand Up @@ -150,7 +178,7 @@ def _find_layout(name, details)
view_paths.find(name, details, prefix)
end

# Returns the default layout for this controller and a given set of details.
# Returns the default layout for this controller and a given set of details.
# Optionally raises an exception if the layout could not be found.
#
# ==== Parameters
Expand All @@ -176,21 +204,8 @@ def _default_layout(details, require_layout = false)
end
end

# Determines whether the current action has a layout by checking the
# action name against the :only and :except conditions set on the
# layout.
#
# ==== Returns
# Boolean:: True if the action has a layout, false otherwise.
def _action_has_layout?
conditions = _layout_conditions
if only = conditions[:only]
only.include?(action_name)
elsif except = conditions[:except]
!except.include?(action_name)
else
true
end
true
end
end
end
7 changes: 3 additions & 4 deletions actionpack/lib/action_controller/metal/compatibility.rb
Expand Up @@ -102,11 +102,10 @@ def render_to_body(options)
options[:template].sub!(/^\//, '')
end

options[:text] = nil if options[:nothing] == true
options[:text] = nil if options.delete(:nothing) == true
options[:text] = " " if options.key?(:text) && options[:text].nil?

body = super
body = [' '] if body.blank?
body
super || " "
end

def _handle_method_missing
Expand Down
14 changes: 13 additions & 1 deletion actionpack/lib/action_controller/metal/hide_actions.rb
Expand Up @@ -13,7 +13,9 @@ module HideActions
# Overrides AbstractController::Base#action_method? to return false if the
# action name is in the list of hidden actions.
def action_method?(action_name)
!hidden_actions.include?(action_name) && super
self.class.visible_action?(action_name) do
!hidden_actions.include?(action_name) && super
end
end

module ClassMethods
Expand All @@ -25,6 +27,16 @@ def hide_action(*args)
hidden_actions.merge(args.map! {|a| a.to_s })
end

def inherited(klass)
klass.instance_variable_set("@visible_actions", {})
super
end

def visible_action?(action_name)
return @visible_actions[action_name] if @visible_actions.key?(action_name)
@visible_actions[action_name] = yield
end

# Overrides AbstractController::Base#action_methods to remove any methods
# that are listed as hidden methods.
def action_methods
Expand Down
10 changes: 1 addition & 9 deletions actionpack/lib/action_controller/metal/url_for.rb
Expand Up @@ -4,15 +4,6 @@ module UrlFor

include RackConvenience

def process_action(*)
initialize_current_url
super
end

def initialize_current_url
@url = UrlRewriter.new(request, params.clone)
end

# Overwrite to implement a number of default options that all url_for-based methods will use. The default options should come in
# the form of a hash, just like the one you would use for url_for directly. Example:
#
Expand Down Expand Up @@ -40,6 +31,7 @@ def url_for(options = {})
when String
options
when Hash
@url ||= UrlRewriter.new(request, params)
@url.rewrite(rewrite_options(options))
else
polymorphic_url(options)
Expand Down
2 changes: 1 addition & 1 deletion actionpack/lib/action_controller/testing/process.rb
Expand Up @@ -52,7 +52,7 @@ def recycle!
class TestResponse < ActionDispatch::TestResponse
def recycle!
@status = 200
@header = ActionDispatch::Response::SimpleHeaderHash.new
@header = {}
@writer = lambda { |x| @body << x }
@block = nil
@length = 0
Expand Down
1 change: 0 additions & 1 deletion actionpack/lib/action_controller/testing/test_case.rb
Expand Up @@ -179,7 +179,6 @@ def setup_controller_request_and_response
if @controller
@controller.request = @request
@controller.params = {}
@controller.send(:initialize_current_url)
end
end

Expand Down
37 changes: 10 additions & 27 deletions actionpack/lib/action_dispatch/http/request.rb
Expand Up @@ -173,21 +173,16 @@ def format(view_path = [])
end
end

# Expand raw_formats by converting Mime::ALL to the Mime::SET.
#
def formats
return raw_formats
# if ActionController::Base.use_accept_header
# raw_formats.tap do |ret|
# if ret == ONLY_ALL
# ret.replace Mime::SET
# elsif all = ret.index(Mime::ALL)
# ret.delete_at(all) && ret.insert(all, *Mime::SET)
# end
# end
# else
# raw_formats + Mime::SET
# end
if ActionController::Base.use_accept_header
if param = parameters[:format]
Array.wrap(Mime[param])
else
accepts.dup
end
else
[format]
end
end

# Sets the \format by string extension, which can be used to force custom formats
Expand Down Expand Up @@ -488,7 +483,7 @@ def flash
# matches the order array.
#
def negotiate_mime(order)
raw_formats.each do |priority|
formats.each do |priority|
if priority == Mime::ALL
return order.first
elsif order.include?(priority)
Expand All @@ -501,18 +496,6 @@ def negotiate_mime(order)

private

def raw_formats
if ActionController::Base.use_accept_header
if param = parameters[:format]
Array.wrap(Mime[param])
else
accepts.dup
end
else
[format]
end
end

def named_host?(host)
!(host.nil? || /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.match(host))
end
Expand Down

0 comments on commit 4bf516e

Please sign in to comment.