Skip to content
This repository
Browse code

Compile ActionController::Base.config's methods to avoid method_missi…

…ng overhead.
  • Loading branch information...
commit 918dc27345319fbabf25a43bd65b613878b3a66e 1 parent 7918a5c
authored September 27, 2010
10  actionpack/lib/action_controller/railtie.rb
@@ -26,6 +26,10 @@ class Railtie < Rails::Railtie
26 26
       options.stylesheets_dir      ||= paths.public.stylesheets.to_a.first
27 27
       options.page_cache_directory ||= paths.public.to_a.first
28 28
 
  29
+      # make sure readers methods get compiled
  30
+      options.asset_path           ||= nil
  31
+      options.asset_host           ||= nil
  32
+
29 33
       ActiveSupport.on_load(:action_controller) do
30 34
         include app.routes.mounted_helpers
31 35
         extend ::AbstractController::Railties::RoutesHelpers.with(app.routes)
@@ -33,5 +37,11 @@ class Railtie < Rails::Railtie
33 37
         options.each { |k,v| send("#{k}=", v) }
34 38
       end
35 39
     end
  40
+
  41
+    config.after_initialize do
  42
+      ActiveSupport.on_load(:action_controller) do
  43
+        config.crystalize! if config.respond_to?(:crystalize!)
  44
+      end
  45
+    end
36 46
   end
37 47
 end
3  actionpack/lib/action_view/base.rb
@@ -209,8 +209,7 @@ def initialize(lookup_context = nil, assigns_for_first_render = {}, controller =
209 209
         @_request = controller.request if controller.respond_to?(:request)
210 210
       end
211 211
 
212  
-      config = controller && controller.respond_to?(:config) ? controller.config : {}
213  
-      @_config = ActiveSupport::InheritableOptions.new(config)
  212
+      @_config = controller && controller.respond_to?(:config) ? controller.config.inheritable_copy : {}
214 213
 
215 214
       @_content_for  = Hash.new { |h,k| h[k] = ActiveSupport::SafeBuffer.new }
216 215
       @_virtual_path = nil
24  activesupport/lib/active_support/configurable.rb
@@ -9,9 +9,29 @@ module ActiveSupport
9 9
   module Configurable
10 10
     extend ActiveSupport::Concern
11 11
 
  12
+    class Configuration < ActiveSupport::InheritableOptions
  13
+      def crystalize!
  14
+        self.class.crystalize!(keys.reject {|key| respond_to?(key)})
  15
+      end
  16
+
  17
+      # compiles reader methods so we don't have to go through method_missing
  18
+      def self.crystalize!(keys)
  19
+        keys.each do |key|
  20
+          class_eval <<-RUBY, __FILE__, __LINE__ + 1
  21
+            def #{key}; self[#{key.inspect}]; end
  22
+          RUBY
  23
+        end
  24
+      end
  25
+    end
  26
+
12 27
     module ClassMethods
13 28
       def config
14  
-        @_config ||= ActiveSupport::InheritableOptions.new(superclass.respond_to?(:config) ? superclass.config : {})
  29
+        @_config ||= if superclass.respond_to?(:config)
  30
+          superclass.config.inheritable_copy
  31
+        else
  32
+          # create a new "anonymous" class that will host the compiled reader methods
  33
+          Class.new(Configuration).new({})
  34
+        end
15 35
       end
16 36
 
17 37
       def configure
@@ -48,7 +68,7 @@ def #{name}=(value); config.#{name} = value; end
48 68
     #   user.config.level          # => 1
49 69
     # 
50 70
     def config
51  
-      @_config ||= ActiveSupport::InheritableOptions.new(self.class.config)
  71
+      @_config ||= self.class.config.inheritable_copy
52 72
     end
53 73
   end
54 74
 end
4  activesupport/lib/active_support/ordered_options.rb
@@ -39,5 +39,9 @@ class InheritableOptions < OrderedOptions
39 39
     def initialize(parent)
40 40
       super() { |h,k| parent[k] }
41 41
     end
  42
+
  43
+    def inheritable_copy
  44
+      self.class.new(self)
  45
+    end
42 46
   end
43 47
 end
18  activesupport/test/configurable_test.rb
@@ -39,4 +39,22 @@ class Child < Parent
39 39
     assert_equal :baz, instance.config.foo
40 40
     assert_equal :bar, Parent.config.foo
41 41
   end
  42
+
  43
+  test "configuration is crystalizeable" do
  44
+    parent = Class.new { include ActiveSupport::Configurable }
  45
+    child  = Class.new(parent)
  46
+
  47
+    parent.config.bar = :foo
  48
+    assert !parent.config.respond_to?(:bar)
  49
+    assert !child.config.respond_to?(:bar)
  50
+    assert !child.new.config.respond_to?(:bar)
  51
+
  52
+    parent.config.crystalize!
  53
+    assert_equal :foo, parent.config.bar
  54
+    assert_equal :foo, child.new.config.bar
  55
+
  56
+    assert_respond_to parent.config, :bar
  57
+    assert_respond_to child.config, :bar
  58
+    assert_respond_to child.new.config, :bar
  59
+  end
42 60
 end

0 notes on commit 918dc27

Please sign in to comment.
Something went wrong with that request. Please try again.