Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Changeset 1425

Show
Ignore:
Timestamp:
06/15/05 17:17:58 (3 years ago)
Author:
bitsweat
Message:

r1318@iwill: jeremy | 2005-06-15 01:08:22 -0700
Ticket 1394 - Helper isolation
r1319@iwill: jeremy | 2005-06-15 01:10:00 -0700
Formulate a test case for helper isolation.
r1331@iwill: jeremy | 2005-06-15 15:21:07 -0700
Update changelog
r1332@iwill: jeremy | 2005-06-15 15:21:30 -0700
Remove superfluous, broken layout_test
r1333@iwill: jeremy | 2005-06-15 15:24:10 -0700
Use an anonymous Module to store helpers per-class instead of tossing them all in template_class. Create a new helper module for subclasses which includes its superclass' helper module. Remove unnecessary ActionView::Base.controller_delegate. Update helper tests.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/actionpack/CHANGELOG

    r1424 r1425  
    11*SVN* 
     2 
     3* Ensure that helpers are only available to the controllers where they are defined and their subclasses.  #1394 [kdole@tamu.edu] 
    24 
    35* render("foo/bar") works with a layout again  
  • trunk/actionpack/lib/action_controller/helpers.rb

    r990 r1425  
    33    def self.append_features(base) 
    44      super 
    5       base.class_eval { class << self; alias_method :inherited_without_helper, :inherited; end } 
     5 
     6      # Initialize the base module to aggregate its helpers. 
     7      base.class_inheritable_accessor :master_helper_module 
     8      base.master_helper_module = Module.new 
     9 
     10      # Extend base with class methods to declare helpers. 
    611      base.extend(ClassMethods) 
     12 
     13      base.class_eval do 
     14        # Wrap inherited to create a new master helper module for subclasses. 
     15        class << self 
     16          alias_method :inherited_without_helper, :inherited 
     17          alias_method :inherited, :inherited_with_helper 
     18        end 
     19 
     20        # Wrap initialize_template_class to extend new template class 
     21        # instances with the master helper module. 
     22        alias_method :initialize_template_class_without_helper, :initialize_template_class 
     23        alias_method :initialize_template_class, :initialize_template_class_with_helper 
     24      end 
    725    end 
    826 
     
    3351      # available to the templates. 
    3452      def add_template_helper(helper_module) #:nodoc: 
    35         template_class.class_eval "include #{helper_module}" 
     53        master_helper_module.module_eval "include #{helper_module}" 
    3654      end 
    3755 
     
    6987 
    7088        # Evaluate block in template class if given. 
    71         template_class.module_eval(&block) if block_given? 
     89        master_helper_module.module_eval(&block) if block_given? 
    7290      end 
    7391 
     
    7795      # makes the link_to controller method available in the view. 
    7896      def helper_method(*methods) 
    79         template_class.controller_delegate(*methods) 
     97        methods.flatten.each do |method| 
     98          master_helper_module.module_eval <<-end_eval 
     99            def #{method}(*args, &block) 
     100              controller.send(%(#{method}), *args, &block) 
     101            end 
     102          end_eval 
     103        end 
    80104      end 
    81105 
     
    90114 
    91115      private  
    92         def inherited(child) 
     116        def inherited_with_helper(child) 
    93117          inherited_without_helper(child) 
    94           begin child.helper(child.controller_path) 
     118          begin 
     119            child.master_helper_module = Module.new 
     120            child.master_helper_module.send :include, master_helper_module 
     121            child.helper child.controller_path 
    95122          rescue MissingSourceFile => e 
    96123            raise unless e.is_missing?("helpers/#{child.controller_path}_helper") 
     
    98125        end         
    99126    end 
     127 
     128    private 
     129      # Extend the template class instance with our controller's helper module. 
     130      def initialize_template_class_with_helper(response) 
     131        returning(initialize_template_class_without_helper(response)) do 
     132          response.template.extend self.class.master_helper_module 
     133        end 
     134      end 
    100135  end 
    101136end 
  • trunk/actionpack/lib/action_view/base.rb

    r1379 r1425  
    142142 
    143143        class_eval("include ActionView::Helpers::#{helper_module_name}") if Helpers.const_defined?(helper_module_name) 
    144       end 
    145     end 
    146  
    147     def self.controller_delegate(*methods)#:nodoc: 
    148       methods.flatten.each do |method| 
    149         class_eval <<-end_eval 
    150           def #{method}(*args, &block) 
    151             controller.send(%(#{method}), *args, &block) 
    152           end 
    153         end_eval 
    154144      end 
    155145    end 
  • trunk/actionpack/test/controller/helper_test.rb

    r1174 r1425  
    1010  class GamesController < ActionController::Base 
    1111    def render_hello_world 
    12       render_template "hello: <%= stratego %>" 
     12      render :inline => "hello: <%= stratego %>" 
    1313    end 
    1414 
     
    2424 
    2525class HelperTest < Test::Unit::TestCase 
    26  
    2726  def setup 
    2827    # Increment symbol counter. 
     
    5150 
    5251  def test_deprecated_helper 
    53     assert_equal helper_methods, missing_methods 
     52    assert_equal expected_helper_methods, missing_methods 
    5453    assert_nothing_raised { @controller_class.helper TestHelper } 
    5554    assert_equal [], missing_methods 
     
    5958    require 'abc_helper' 
    6059    self.test_helper = AbcHelper 
    61     assert_equal helper_methods, missing_methods 
     60    assert_equal expected_helper_methods, missing_methods 
    6261    assert_nothing_raised { @controller_class.helper :abc } 
    6362    assert_equal [], missing_methods 
     
    6564 
    6665  def test_declare_missing_helper 
    67     assert_equal helper_methods, missing_methods 
     66    assert_equal expected_helper_methods, missing_methods 
    6867    assert_raise(MissingSourceFile) { @controller_class.helper :missing } 
    6968  end 
     
    7978      @controller_class.helper { def block_helper_method; end } 
    8079    } 
    81     assert template_methods.include?('block_helper_method') 
     80    assert master_helper_methods.include?('block_helper_method') 
    8281  end 
    8382 
    8483  def test_helper_block_include 
    85     assert_equal helper_methods, missing_methods 
     84    assert_equal expected_helper_methods, missing_methods 
    8685    assert_nothing_raised { 
    8786      @controller_class.helper { include TestHelper } 
     
    9291  def test_helper_method 
    9392    assert_nothing_raised { @controller_class.helper_method :delegate_method } 
    94     assert template_methods.include?('delegate_method') 
     93    assert master_helper_methods.include?('delegate_method') 
    9594  end 
    9695 
    9796  def test_helper_attr 
    9897    assert_nothing_raised { @controller_class.helper_attr :delegate_attr } 
    99     assert template_methods.include?('delegate_attr') 
    100     assert template_methods.include?('delegate_attr=') 
     98    assert master_helper_methods.include?('delegate_attr') 
     99    assert master_helper_methods.include?('delegate_attr=') 
    101100  end 
    102101 
     
    110109 
    111110  private 
    112     def helper_methods;   TestHelper.instance_methods      end 
    113     def template_methods; @template_class.instance_methods  end 
    114     def missing_methods;  helper_methods - template_methods end 
     111    def expected_helper_methods 
     112      TestHelper.instance_methods 
     113    end 
     114 
     115    def master_helper_methods 
     116      @controller_class.master_helper_module.instance_methods 
     117    end 
     118 
     119    def missing_methods 
     120      expected_helper_methods - master_helper_methods 
     121    end 
    115122 
    116123    def test_helper=(helper_module) 
     
    120127    end 
    121128end 
     129 
     130 
     131class IsolatedHelpersTest < Test::Unit::TestCase 
     132  class A < ActionController::Base 
     133    def index 
     134      render :inline => '<%= shout %>' 
     135    end 
     136 
     137    def rescue_action(e) raise end 
     138  end 
     139 
     140  class B < A 
     141    helper { def shout; 'B' end } 
     142 
     143    def index 
     144      render :inline => '<%= shout %>' 
     145    end 
     146  end 
     147 
     148  class C < A 
     149    helper { def shout; 'C' end } 
     150 
     151    def index 
     152      render :inline => '<%= shout %>' 
     153    end 
     154  end 
     155 
     156  def setup 
     157    @request    = ActionController::TestRequest.new 
     158    @response   = ActionController::TestResponse.new 
     159    @request.action = 'index' 
     160  end 
     161 
     162  def test_helper_in_a 
     163    assert_raise(NameError) { A.process(@request, @response) } 
     164  end 
     165 
     166  def test_helper_in_b 
     167    assert_equal 'B', B.process(@request, @response).body 
     168  end 
     169 
     170  def test_helper_in_c 
     171    assert_equal 'C', C.process(@request, @response).body 
     172  end 
     173end