mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Optimize LookupContext
This commit is contained in:
parent
16ee4b4d1b
commit
a6b3942843
6 changed files with 75 additions and 14 deletions
|
@ -12,6 +12,7 @@ module ActionDispatch
|
|||
def initialize(options={})
|
||||
@defaults = options[:defaults]
|
||||
@glob_param = options.delete(:glob)
|
||||
@controllers = {}
|
||||
end
|
||||
|
||||
def call(env)
|
||||
|
@ -32,9 +33,15 @@ module ActionDispatch
|
|||
end
|
||||
|
||||
def controller(params, raise_error=true)
|
||||
if params && params.has_key?(:controller)
|
||||
controller = "#{params[:controller].camelize}Controller"
|
||||
ActiveSupport::Inflector.constantize(controller)
|
||||
if params && params.key?(:controller)
|
||||
controller_param = params[:controller]
|
||||
unless controller = @controllers[controller_param]
|
||||
controller_name = "#{controller_param.camelize}Controller"
|
||||
controller = @controllers[controller_param] =
|
||||
ActiveSupport::Dependencies.ref(controller_name)
|
||||
end
|
||||
|
||||
controller.get
|
||||
end
|
||||
rescue NameError => e
|
||||
raise ActionController::RoutingError, e.message, e.backtrace if raise_error
|
||||
|
|
|
@ -201,6 +201,7 @@ module ActionView #:nodoc:
|
|||
end
|
||||
|
||||
def self.process_view_paths(value)
|
||||
return value.dup if value.is_a?(PathSet)
|
||||
ActionView::PathSet.new(Array.wrap(value))
|
||||
end
|
||||
|
||||
|
|
|
@ -13,8 +13,12 @@ module ActionView
|
|||
mattr_accessor :registered_details
|
||||
self.registered_details = []
|
||||
|
||||
mattr_accessor :registered_detail_setters
|
||||
self.registered_detail_setters = []
|
||||
|
||||
def self.register_detail(name, options = {}, &block)
|
||||
self.registered_details << name
|
||||
self.registered_detail_setters << [name, "#{name}="]
|
||||
Accessors.send :define_method, :"_#{name}_defaults", &block
|
||||
Accessors.module_eval <<-METHOD, __FILE__, __LINE__ + 1
|
||||
def #{name}
|
||||
|
@ -60,7 +64,7 @@ module ActionView
|
|||
@details, @details_key = { :handlers => default_handlers }, nil
|
||||
@frozen_formats, @skip_default_locale = false, false
|
||||
self.view_paths = view_paths
|
||||
self.update_details(details, true)
|
||||
self.initialize_details(details)
|
||||
end
|
||||
|
||||
module ViewPaths
|
||||
|
@ -116,11 +120,11 @@ module ActionView
|
|||
end
|
||||
|
||||
def default_handlers #:nodoc:
|
||||
@default_handlers ||= Template::Handlers.extensions
|
||||
@@default_handlers ||= Template::Handlers.extensions
|
||||
end
|
||||
|
||||
def handlers_regexp #:nodoc:
|
||||
@handlers_regexp ||= /\.(?:#{default_handlers.join('|')})$/
|
||||
@@handlers_regexp ||= /\.(?:#{default_handlers.join('|')})$/
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -141,10 +145,13 @@ module ActionView
|
|||
end
|
||||
|
||||
# Overload formats= to reject [:"*/*"] values.
|
||||
def formats=(value)
|
||||
value = nil if value == [:"*/*"]
|
||||
value << :html if value == [:js]
|
||||
super(value)
|
||||
def formats=(values)
|
||||
if values && values.size == 1
|
||||
value = values.first
|
||||
values = nil if value == :"*/*"
|
||||
values << :html if value == :js
|
||||
end
|
||||
super(values)
|
||||
end
|
||||
|
||||
# Do not use the default locale on template lookup.
|
||||
|
@ -170,14 +177,22 @@ module ActionView
|
|||
super(@skip_default_locale ? I18n.locale : _locale_defaults)
|
||||
end
|
||||
|
||||
def initialize_details(details)
|
||||
details = details.dup
|
||||
|
||||
registered_detail_setters.each do |key, setter|
|
||||
send(setter, details[key])
|
||||
end
|
||||
end
|
||||
|
||||
# Update the details keys by merging the given hash into the current
|
||||
# details hash. If a block is given, the details are modified just during
|
||||
# the execution of the block and reverted to the previous value after.
|
||||
def update_details(new_details, force=false)
|
||||
def update_details(new_details)
|
||||
old_details = @details.dup
|
||||
|
||||
registered_details.each do |key|
|
||||
send(:"#{key}=", new_details[key]) if force || new_details.key?(key)
|
||||
registered_detail_setters.each do |key, setter|
|
||||
send(setter, new_details[key]) if new_details.key?(key)
|
||||
end
|
||||
|
||||
if block_given?
|
||||
|
|
|
@ -19,7 +19,7 @@ module ActionView #:nodoc:
|
|||
@@default_template_handlers = nil
|
||||
|
||||
def self.extensions
|
||||
@@template_handlers.keys
|
||||
@@template_extensions ||= @@template_handlers.keys
|
||||
end
|
||||
|
||||
# Register a class that knows how to handle template files with the given
|
||||
|
|
|
@ -47,6 +47,9 @@ module ActiveSupport #:nodoc:
|
|||
mattr_accessor :autoloaded_constants
|
||||
self.autoloaded_constants = []
|
||||
|
||||
mattr_accessor :references
|
||||
self.references = {}
|
||||
|
||||
# An array of constant names that need to be unloaded on every request. Used
|
||||
# to allow arbitrary constants to be marked for unloading.
|
||||
mattr_accessor :explicitly_unloadable_constants
|
||||
|
@ -476,9 +479,28 @@ module ActiveSupport #:nodoc:
|
|||
def remove_unloadable_constants!
|
||||
autoloaded_constants.each { |const| remove_constant const }
|
||||
autoloaded_constants.clear
|
||||
references.each {|k,v| v.clear! }
|
||||
explicitly_unloadable_constants.each { |const| remove_constant const }
|
||||
end
|
||||
|
||||
class Reference
|
||||
def initialize(constant, name)
|
||||
@constant, @name = constant, name
|
||||
end
|
||||
|
||||
def get
|
||||
@constant ||= Inflector.constantize(@name)
|
||||
end
|
||||
|
||||
def clear!
|
||||
@constant = nil
|
||||
end
|
||||
end
|
||||
|
||||
def ref(name)
|
||||
references[name] ||= Reference.new(Inflector.constantize(name), name)
|
||||
end
|
||||
|
||||
# Determine if the given constant has been automatically loaded.
|
||||
def autoloaded?(desc)
|
||||
# No name => anonymous module.
|
||||
|
@ -572,6 +594,7 @@ module ActiveSupport #:nodoc:
|
|||
|
||||
log "removing constant #{const}"
|
||||
parent.instance_eval { remove_const to_remove }
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
|
|
|
@ -431,6 +431,21 @@ class DependenciesTest < Test::Unit::TestCase
|
|||
end
|
||||
end
|
||||
|
||||
def test_references_should_work
|
||||
with_loading 'dependencies' do
|
||||
root = ActiveSupport::Dependencies.load_paths.first
|
||||
c = ActiveSupport::Dependencies.ref("ServiceOne")
|
||||
service_one_first = ServiceOne
|
||||
assert_equal service_one_first, c.get
|
||||
ActiveSupport::Dependencies.clear
|
||||
assert ! defined?(ServiceOne)
|
||||
|
||||
service_one_second = ServiceOne
|
||||
assert_not_equal service_one_first, c.get
|
||||
assert_equal service_one_second, c.get
|
||||
end
|
||||
end
|
||||
|
||||
def test_nested_load_error_isnt_rescued
|
||||
with_loading 'dependencies' do
|
||||
assert_raise(MissingSourceFile) do
|
||||
|
|
Loading…
Reference in a new issue