Skip to content

Commit

Permalink
Merge commit 'rails/master'
Browse files Browse the repository at this point in the history
Conflicts:
	activerecord/lib/active_record/calculations.rb
  • Loading branch information
miloops committed Aug 17, 2009
2 parents 770fca1 + ccf28d2 commit c01c896
Show file tree
Hide file tree
Showing 41 changed files with 619 additions and 1,143 deletions.
13 changes: 9 additions & 4 deletions actionpack/lib/abstract_controller/layouts.rb
Expand Up @@ -19,15 +19,20 @@ def inherited(klass)
end end
end end


def clear_template_caches!
@found_layouts.clear if @found_layouts
super
end

def cache_layout(details) def cache_layout(details)
layout = @found_layouts layout = @found_layouts
values = details.values_at(:formats, :locale) key = Thread.current[:format_locale_key]


# Cache nil # Cache nil
if layout.key?(values) if layout.key?(key)
return layout[values] return layout[key]
else else
layout[values] = yield layout[key] = yield
end end
end end


Expand Down
17 changes: 14 additions & 3 deletions actionpack/lib/abstract_controller/rendering_controller.rb
Expand Up @@ -111,12 +111,21 @@ def self.body_to_s(body)
def _determine_template(options) def _determine_template(options)
name = (options[:_template_name] || action_name).to_s name = (options[:_template_name] || action_name).to_s


options[:_template] ||= view_paths.find( options[:_template] ||= with_template_cache(name) do
name, { :formats => formats }, options[:_prefix], options[:_partial] view_paths.find(
) name, { :formats => formats }, options[:_prefix], options[:_partial]
)
end
end

def with_template_cache(name)
yield
end end


module ClassMethods module ClassMethods
def clear_template_caches!
end

# Append a path to the list of view paths for this controller. # Append a path to the list of view paths for this controller.
# #
# ==== Parameters # ==== Parameters
Expand All @@ -134,6 +143,7 @@ def append_view_path(path)
# the default view path. You may also provide a custom view path # the default view path. You may also provide a custom view path
# (see ActionView::ViewPathSet for more information) # (see ActionView::ViewPathSet for more information)
def prepend_view_path(path) def prepend_view_path(path)
clear_template_caches!
self.view_paths.unshift(path) self.view_paths.unshift(path)
end end


Expand All @@ -148,6 +158,7 @@ def view_paths
# paths<ViewPathSet, Object>:: If a ViewPathSet is provided, use that; # paths<ViewPathSet, Object>:: If a ViewPathSet is provided, use that;
# otherwise, process the parameter into a ViewPathSet. # otherwise, process the parameter into a ViewPathSet.
def view_paths=(paths) def view_paths=(paths)
clear_template_caches!
self._view_paths = paths.is_a?(ActionView::PathSet) ? self._view_paths = paths.is_a?(ActionView::PathSet) ?
paths : ActionView::Base.process_view_paths(paths) paths : ActionView::Base.process_view_paths(paths)
end end
Expand Down
48 changes: 44 additions & 4 deletions actionpack/lib/action_controller/metal/rendering_controller.rb
@@ -1,20 +1,56 @@
module ActionController module ActionController
class HashKey
@hash_keys = Hash.new {|h,k| h[k] = Hash.new {|h,k| h[k] = {} } }

def self.get(klass, formats, locale)
@hash_keys[klass][formats][locale] ||= new(klass, formats, locale)
end

attr_accessor :hash
def initialize(klass, formats, locale)
@formats, @locale = formats, locale
@hash = [formats, locale].hash
end

alias_method :eql?, :equal?

def inspect
"#<HashKey -- formats: #{@formats} locale: #{@locale}>"
end
end

module RenderingController module RenderingController
extend ActiveSupport::Concern extend ActiveSupport::Concern


include AbstractController::RenderingController include AbstractController::RenderingController


module ClassMethods
def clear_template_caches!
ActionView::Partials::PartialRenderer::TEMPLATES.clear
template_cache.clear
super
end

def template_cache
@template_cache ||= Hash.new {|h,k| h[k] = {} }
end
end

def process_action(*) def process_action(*)
self.formats = request.formats.map {|x| x.to_sym} self.formats = request.formats.map {|x| x.to_sym}

super
end

def _determine_template(*)
super super
end end


def render(options) def render(options)
Thread.current[:format_locale_key] = HashKey.get(self.class, formats, I18n.locale)

super super
self.content_type ||= begin self.content_type ||= options[:_template].mime_type.to_s
mime = options[:_template].mime_type
formats.include?(mime && mime.to_sym) || formats.include?(:all) ? mime : Mime::Type.lookup_by_extension(formats.first)
end.to_s
response_body response_body
end end


Expand All @@ -34,6 +70,10 @@ def _prefix
controller_path controller_path
end end


def with_template_cache(name)
self.class.template_cache[Thread.current[:format_locale_key]][name] ||= super
end

def _determine_template(options) def _determine_template(options)
if options.key?(:text) if options.key?(:text)
options[:_template] = ActionView::TextTemplate.new(options[:text], formats.first) options[:_template] = ActionView::TextTemplate.new(options[:text], formats.first)
Expand Down
18 changes: 9 additions & 9 deletions actionpack/lib/action_controller/routing/resources.rb
Expand Up @@ -531,31 +531,31 @@ def map_resource(entities, options = {}, &block)
with_options :controller => resource.controller do |map| with_options :controller => resource.controller do |map|
map_associations(resource, options) map_associations(resource, options)


if block_given?
with_options(options.slice(*INHERITABLE_OPTIONS).merge(:path_prefix => resource.nesting_path_prefix, :name_prefix => resource.nesting_name_prefix), &block)
end

map_collection_actions(map, resource) map_collection_actions(map, resource)
map_default_collection_actions(map, resource) map_default_collection_actions(map, resource)
map_new_actions(map, resource) map_new_actions(map, resource)
map_member_actions(map, resource) map_member_actions(map, resource)

if block_given?
with_options(options.slice(*INHERITABLE_OPTIONS).merge(:path_prefix => resource.nesting_path_prefix, :name_prefix => resource.nesting_name_prefix), &block)
end
end end
end end


def map_singleton_resource(entities, options = {}, &block) def map_singleton_resource(entities, options = {}, &block)
resource = SingletonResource.new(entities, options) resource = SingletonResource.new(entities, options)


with_options :controller => resource.controller do |map| with_options :controller => resource.controller do |map|
map_collection_actions(map, resource)
map_new_actions(map, resource)
map_member_actions(map, resource)
map_default_singleton_actions(map, resource)

map_associations(resource, options) map_associations(resource, options)


if block_given? if block_given?
with_options(options.slice(*INHERITABLE_OPTIONS).merge(:path_prefix => resource.nesting_path_prefix, :name_prefix => resource.nesting_name_prefix), &block) with_options(options.slice(*INHERITABLE_OPTIONS).merge(:path_prefix => resource.nesting_path_prefix, :name_prefix => resource.nesting_name_prefix), &block)
end end

map_collection_actions(map, resource)
map_new_actions(map, resource)
map_member_actions(map, resource)
map_default_singleton_actions(map, resource)
end end
end end


Expand Down
29 changes: 2 additions & 27 deletions actionpack/lib/action_controller/routing/route_set.rb
Expand Up @@ -407,22 +407,9 @@ def generate(options, recall = {}, method=:generate)
# don't use the recalled keys when determining which routes to check # don't use the recalled keys when determining which routes to check
routes = routes_by_controller[controller][action][options.reject {|k,v| !v}.keys.sort_by { |x| x.object_id }] routes = routes_by_controller[controller][action][options.reject {|k,v| !v}.keys.sort_by { |x| x.object_id }]


routes[1].each_with_index do |route, index| routes.each_with_index do |route, index|
results = route.__send__(method, options, merged, expire_on) results = route.__send__(method, options, merged, expire_on)
if results && (!results.is_a?(Array) || results.first) if results && (!results.is_a?(Array) || results.first)

# Compare results with Rails 3.0 behavior
if routes[0][index] != route
routes[0].each do |route2|
new_results = route2.__send__(method, options, merged, expire_on)
if new_results && (!new_results.is_a?(Array) || new_results.first)
ActiveSupport::Deprecation.warn "The URL you generated will use the first matching route in routes.rb rather than the \"best\" match. " +
"In Rails 3.0 #{new_results} would of been generated instead of #{results}"
break
end
end
end

return results return results
end end
end end
Expand Down Expand Up @@ -463,10 +450,7 @@ def routes_by_controller
@routes_by_controller ||= Hash.new do |controller_hash, controller| @routes_by_controller ||= Hash.new do |controller_hash, controller|
controller_hash[controller] = Hash.new do |action_hash, action| controller_hash[controller] = Hash.new do |action_hash, action|
action_hash[action] = Hash.new do |key_hash, keys| action_hash[action] = Hash.new do |key_hash, keys|
key_hash[keys] = [ key_hash[keys] = routes_for_controller_and_action_and_keys(controller, action, keys)
routes_for_controller_and_action_and_keys(controller, action, keys),
deprecated_routes_for_controller_and_action_and_keys(controller, action, keys)
]
end end
end end
end end
Expand All @@ -487,15 +471,6 @@ def routes_for_controller_and_action_and_keys(controller, action, keys)
end end
end end


def deprecated_routes_for_controller_and_action_and_keys(controller, action, keys)
selected = routes.select do |route|
route.matches_controller_and_action? controller, action
end
selected.sort_by do |route|
(keys - route.significant_keys).length
end
end

# Subclasses and plugins may override this method to extract further attributes # Subclasses and plugins may override this method to extract further attributes
# from the request, for use by route conditions and such. # from the request, for use by route conditions and such.
def extract_request_environment(request) def extract_request_environment(request)
Expand Down
2 changes: 1 addition & 1 deletion actionpack/lib/action_controller/testing/process.rb
Expand Up @@ -148,7 +148,7 @@ def process(action, parameters = nil, session = nil, flash = nil, http_method =


def xml_http_request(request_method, action, parameters = nil, session = nil, flash = nil) def xml_http_request(request_method, action, parameters = nil, session = nil, flash = nil)
@request.env['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest' @request.env['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'
@request.env['HTTP_ACCEPT'] = [Mime::JS, Mime::HTML, Mime::XML, 'text/xml', Mime::ALL].join(', ') @request.env['HTTP_ACCEPT'] ||= [Mime::JS, Mime::HTML, Mime::XML, 'text/xml', Mime::ALL].join(', ')
returning __send__(request_method, action, parameters, session, flash) do returning __send__(request_method, action, parameters, session, flash) do
@request.env.delete 'HTTP_X_REQUESTED_WITH' @request.env.delete 'HTTP_X_REQUESTED_WITH'
@request.env.delete 'HTTP_ACCEPT' @request.env.delete 'HTTP_ACCEPT'
Expand Down
36 changes: 12 additions & 24 deletions actionpack/lib/action_dispatch/http/request.rb
Expand Up @@ -106,16 +106,10 @@ def accepts
@env["action_dispatch.request.accepts"] ||= begin @env["action_dispatch.request.accepts"] ||= begin
header = @env['HTTP_ACCEPT'].to_s.strip header = @env['HTTP_ACCEPT'].to_s.strip


fallback = xhr? ? Mime::JS : Mime::HTML

if header.empty? if header.empty?
[content_type, fallback, Mime::ALL].compact [content_type]
else else
ret = Mime::Type.parse(header) Mime::Type.parse(header)
if ret.last == Mime::ALL
ret.insert(-2, fallback)
end
ret
end end
end end
end end
Expand Down Expand Up @@ -163,26 +157,20 @@ def fresh?(response)
# GET /posts/5 | request.format => Mime::HTML or MIME::JS, or request.accepts.first depending on the value of <tt>ActionController::Base.use_accept_header</tt> # GET /posts/5 | request.format => Mime::HTML or MIME::JS, or request.accepts.first depending on the value of <tt>ActionController::Base.use_accept_header</tt>
# #
def format(view_path = []) def format(view_path = [])
@env["action_dispatch.request.format"] ||= formats.first
if parameters[:format]
Mime[parameters[:format]]
elsif ActionController::Base.use_accept_header && !(accepts == ONLY_ALL)
accepts.first
elsif xhr? then Mime::JS
else Mime::HTML
end
end end


def formats def formats
if ActionController::Base.use_accept_header accept = @env['HTTP_ACCEPT']
if param = parameters[:format]
Array.wrap(Mime[param]) @env["action_dispatch.request.formats"] ||=
if parameters[:format]
[Mime[parameters[:format]]]
elsif xhr? || (accept && !accept.include?(?,))
accepts
else else
accepts.dup [Mime::HTML]
end end
else
[format]
end
end end


# Sets the \format by string extension, which can be used to force custom formats # Sets the \format by string extension, which can be used to force custom formats
Expand All @@ -198,7 +186,7 @@ def formats
# end # end
def format=(extension) def format=(extension)
parameters[:format] = extension.to_s parameters[:format] = extension.to_s
@env["action_dispatch.request.format"] = Mime::Type.lookup_by_extension(parameters[:format]) @env["action_dispatch.request.formats"] = [Mime::Type.lookup_by_extension(parameters[:format])]
end end


# Returns a symbolized version of the <tt>:format</tt> parameter of the request. # Returns a symbolized version of the <tt>:format</tt> parameter of the request.
Expand Down
6 changes: 6 additions & 0 deletions actionpack/lib/action_dispatch/middleware/params_parser.rb
Expand Up @@ -47,6 +47,8 @@ def parse_formatted_parameters(env)
false false
end end
rescue Exception => e # YAML, XML or Ruby code block errors rescue Exception => e # YAML, XML or Ruby code block errors
logger.debug "Error occurred while parsing request parameters.\nContents:\n\n#{request.raw_post}"

raise raise
{ "body" => request.raw_post, { "body" => request.raw_post,
"content_type" => request.content_type, "content_type" => request.content_type,
Expand All @@ -67,5 +69,9 @@ def content_type_from_legacy_post_data_format_header(env)


nil nil
end end

def logger
defined?(Rails.logger) ? Rails.logger : Logger.new($stderr)
end
end end
end end
29 changes: 12 additions & 17 deletions actionpack/lib/action_view/base.rb
Expand Up @@ -175,6 +175,17 @@ module Subclasses
attr_accessor :controller attr_accessor :controller
attr_internal :captures attr_internal :captures


def reset_formats(formats)
@formats = formats

if defined?(ActionController)
# This is expensive, but we need to reset this when the format is updated,
# which currently only happens
Thread.current[:format_locale_key] =
ActionController::HashKey.get(self.class, formats, I18n.locale)
end
end

class << self class << self
delegate :erb_trim_mode=, :to => 'ActionView::TemplateHandlers::ERB' delegate :erb_trim_mode=, :to => 'ActionView::TemplateHandlers::ERB'
delegate :logger, :to => 'ActionController::Base', :allow_nil => true delegate :logger, :to => 'ActionController::Base', :allow_nil => true
Expand Down Expand Up @@ -240,7 +251,7 @@ def self.for_controller(controller)
end end


def initialize(view_paths = [], assigns_for_first_render = {}, controller = nil, formats = nil)#:nodoc: def initialize(view_paths = [], assigns_for_first_render = {}, controller = nil, formats = nil)#:nodoc:
@formats = formats || [:html] @formats = formats
@assigns = assigns_for_first_render.each { |key, value| instance_variable_set("@#{key}", value) } @assigns = assigns_for_first_render.each { |key, value| instance_variable_set("@#{key}", value) }
@controller = controller @controller = controller
@helpers = self.class.helpers || Module.new @helpers = self.class.helpers || Module.new
Expand All @@ -255,15 +266,6 @@ def view_paths=(paths)
@view_paths = self.class.process_view_paths(paths) @view_paths = self.class.process_view_paths(paths)
end end


def with_template(current_template)
_evaluate_assigns_and_ivars
last_template, self.template = template, current_template
last_formats, self.formats = formats, current_template.formats
yield
ensure
self.template, self.formats = last_template, last_formats
end

def punctuate_body!(part) def punctuate_body!(part)
flush_output_buffer flush_output_buffer
response.body_parts << part response.body_parts << part
Expand All @@ -272,18 +274,11 @@ def punctuate_body!(part)


# Evaluates the local assigns and controller ivars, pushes them to the view. # Evaluates the local assigns and controller ivars, pushes them to the view.
def _evaluate_assigns_and_ivars #:nodoc: def _evaluate_assigns_and_ivars #:nodoc:
@assigns_added ||= _copy_ivars_from_controller
end

private

def _copy_ivars_from_controller #:nodoc:
if @controller if @controller
variables = @controller.instance_variable_names variables = @controller.instance_variable_names
variables -= @controller.protected_instance_variables if @controller.respond_to?(:protected_instance_variables) variables -= @controller.protected_instance_variables if @controller.respond_to?(:protected_instance_variables)
variables.each { |name| instance_variable_set(name, @controller.instance_variable_get(name)) } variables.each { |name| instance_variable_set(name, @controller.instance_variable_get(name)) }
end end
true
end end


end end
Expand Down

0 comments on commit c01c896

Please sign in to comment.