Skip to content

Commit a6b3942

Browse files
committed
Optimize LookupContext
1 parent 16ee4b4 commit a6b3942

File tree

6 files changed

+75
-14
lines changed

6 files changed

+75
-14
lines changed

actionpack/lib/action_dispatch/routing/route_set.rb

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ class Dispatcher #:nodoc:
1212
def initialize(options={})
1313
@defaults = options[:defaults]
1414
@glob_param = options.delete(:glob)
15+
@controllers = {}
1516
end
1617

1718
def call(env)
@@ -32,9 +33,15 @@ def prepare_params!(params)
3233
end
3334

3435
def controller(params, raise_error=true)
35-
if params && params.has_key?(:controller)
36-
controller = "#{params[:controller].camelize}Controller"
37-
ActiveSupport::Inflector.constantize(controller)
36+
if params && params.key?(:controller)
37+
controller_param = params[:controller]
38+
unless controller = @controllers[controller_param]
39+
controller_name = "#{controller_param.camelize}Controller"
40+
controller = @controllers[controller_param] =
41+
ActiveSupport::Dependencies.ref(controller_name)
42+
end
43+
44+
controller.get
3845
end
3946
rescue NameError => e
4047
raise ActionController::RoutingError, e.message, e.backtrace if raise_error

actionpack/lib/action_view/base.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ def self.xss_safe? #:nodoc:
201201
end
202202

203203
def self.process_view_paths(value)
204+
return value.dup if value.is_a?(PathSet)
204205
ActionView::PathSet.new(Array.wrap(value))
205206
end
206207

actionpack/lib/action_view/lookup_context.rb

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,12 @@ class LookupContext #:nodoc:
1313
mattr_accessor :registered_details
1414
self.registered_details = []
1515

16+
mattr_accessor :registered_detail_setters
17+
self.registered_detail_setters = []
18+
1619
def self.register_detail(name, options = {}, &block)
1720
self.registered_details << name
21+
self.registered_detail_setters << [name, "#{name}="]
1822
Accessors.send :define_method, :"_#{name}_defaults", &block
1923
Accessors.module_eval <<-METHOD, __FILE__, __LINE__ + 1
2024
def #{name}
@@ -60,7 +64,7 @@ def initialize(view_paths, details = {})
6064
@details, @details_key = { :handlers => default_handlers }, nil
6165
@frozen_formats, @skip_default_locale = false, false
6266
self.view_paths = view_paths
63-
self.update_details(details, true)
67+
self.initialize_details(details)
6468
end
6569

6670
module ViewPaths
@@ -116,11 +120,11 @@ def normalize_name(name, prefix) #:nodoc:
116120
end
117121

118122
def default_handlers #:nodoc:
119-
@default_handlers ||= Template::Handlers.extensions
123+
@@default_handlers ||= Template::Handlers.extensions
120124
end
121125

122126
def handlers_regexp #:nodoc:
123-
@handlers_regexp ||= /\.(?:#{default_handlers.join('|')})$/
127+
@@handlers_regexp ||= /\.(?:#{default_handlers.join('|')})$/
124128
end
125129
end
126130

@@ -141,10 +145,13 @@ def freeze_formats(formats, unless_frozen=false) #:nodoc:
141145
end
142146

143147
# Overload formats= to reject [:"*/*"] values.
144-
def formats=(value)
145-
value = nil if value == [:"*/*"]
146-
value << :html if value == [:js]
147-
super(value)
148+
def formats=(values)
149+
if values && values.size == 1
150+
value = values.first
151+
values = nil if value == :"*/*"
152+
values << :html if value == :js
153+
end
154+
super(values)
148155
end
149156

150157
# Do not use the default locale on template lookup.
@@ -170,14 +177,22 @@ def locale=(value)
170177
super(@skip_default_locale ? I18n.locale : _locale_defaults)
171178
end
172179

180+
def initialize_details(details)
181+
details = details.dup
182+
183+
registered_detail_setters.each do |key, setter|
184+
send(setter, details[key])
185+
end
186+
end
187+
173188
# Update the details keys by merging the given hash into the current
174189
# details hash. If a block is given, the details are modified just during
175190
# the execution of the block and reverted to the previous value after.
176-
def update_details(new_details, force=false)
191+
def update_details(new_details)
177192
old_details = @details.dup
178193

179-
registered_details.each do |key|
180-
send(:"#{key}=", new_details[key]) if force || new_details.key?(key)
194+
registered_detail_setters.each do |key, setter|
195+
send(setter, new_details[key]) if new_details.key?(key)
181196
end
182197

183198
if block_given?

actionpack/lib/action_view/template/handlers.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ def self.extended(base)
1919
@@default_template_handlers = nil
2020

2121
def self.extensions
22-
@@template_handlers.keys
22+
@@template_extensions ||= @@template_handlers.keys
2323
end
2424

2525
# Register a class that knows how to handle template files with the given

activesupport/lib/active_support/dependencies.rb

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ module Dependencies #:nodoc:
4747
mattr_accessor :autoloaded_constants
4848
self.autoloaded_constants = []
4949

50+
mattr_accessor :references
51+
self.references = {}
52+
5053
# An array of constant names that need to be unloaded on every request. Used
5154
# to allow arbitrary constants to be marked for unloading.
5255
mattr_accessor :explicitly_unloadable_constants
@@ -476,9 +479,28 @@ def load_missing_constant(from_mod, const_name)
476479
def remove_unloadable_constants!
477480
autoloaded_constants.each { |const| remove_constant const }
478481
autoloaded_constants.clear
482+
references.each {|k,v| v.clear! }
479483
explicitly_unloadable_constants.each { |const| remove_constant const }
480484
end
481485

486+
class Reference
487+
def initialize(constant, name)
488+
@constant, @name = constant, name
489+
end
490+
491+
def get
492+
@constant ||= Inflector.constantize(@name)
493+
end
494+
495+
def clear!
496+
@constant = nil
497+
end
498+
end
499+
500+
def ref(name)
501+
references[name] ||= Reference.new(Inflector.constantize(name), name)
502+
end
503+
482504
# Determine if the given constant has been automatically loaded.
483505
def autoloaded?(desc)
484506
# No name => anonymous module.
@@ -572,6 +594,7 @@ def remove_constant(const) #:nodoc:
572594

573595
log "removing constant #{const}"
574596
parent.instance_eval { remove_const to_remove }
597+
575598
return true
576599
end
577600

activesupport/test/dependencies_test.rb

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,21 @@ def test_removal_from_tree_should_be_detected
431431
end
432432
end
433433

434+
def test_references_should_work
435+
with_loading 'dependencies' do
436+
root = ActiveSupport::Dependencies.load_paths.first
437+
c = ActiveSupport::Dependencies.ref("ServiceOne")
438+
service_one_first = ServiceOne
439+
assert_equal service_one_first, c.get
440+
ActiveSupport::Dependencies.clear
441+
assert ! defined?(ServiceOne)
442+
443+
service_one_second = ServiceOne
444+
assert_not_equal service_one_first, c.get
445+
assert_equal service_one_second, c.get
446+
end
447+
end
448+
434449
def test_nested_load_error_isnt_rescued
435450
with_loading 'dependencies' do
436451
assert_raise(MissingSourceFile) do

0 commit comments

Comments
 (0)