public
Description: Ruby on Rails
Homepage: http://rubyonrails.org
Clone URL: git://github.com/rails/rails.git
Fixed bc5896e, and added test case for the caching bug it originally 
introduced.
josh (author)
Wed Jul 23 11:47:30 -0700 2008
commit  55adaa2efc08c892bf7be55d79ac571848068256
tree    1e52562f708f64d38ad95e57e42ab39c3ff82ab2
parent  e0db925be04ab3e9c3db67dd0daa8caf3680dd21
...
332
333
334
 
 
 
335
336
337
...
332
333
334
335
336
337
338
339
340
0
@@ -332,6 +332,9 @@ module ActionView #:nodoc:
0
       end
0
     end
0
 
0
+ extend ActiveSupport::Memoizable
0
+ memoize :pick_template
0
+
0
     private
0
       # Renders the template present at <tt>template_path</tt>. The hash in <tt>local_assigns</tt>
0
       # is made available as local variables.
...
102
103
104
 
 
105
106
107
...
129
130
131
132
133
134
135
136
137
138
139
 
 
140
141
142
...
153
154
155
 
156
157
...
102
103
104
105
106
107
108
109
...
131
132
133
 
 
134
135
136
137
 
 
138
139
140
141
142
...
153
154
155
156
157
158
0
@@ -102,6 +102,8 @@ module ActionView
0
   #
0
   # As you can see, the <tt>:locals</tt> hash is shared between both the partial and its layout.
0
   module Partials
0
+ extend ActiveSupport::Memoizable
0
+
0
     private
0
       def render_partial(partial_path, object_assigns = nil, local_assigns = {}) #:nodoc:
0
         local_assigns ||= {}
0
@@ -129,14 +131,12 @@ module ActionView
0
 
0
         local_assigns = local_assigns ? local_assigns.clone : {}
0
         spacer = partial_spacer_template ? render(:partial => partial_spacer_template) : ''
0
- _paths = {}
0
- _templates = {}
0
 
0
         index = 0
0
         collection.map do |object|
0
           _partial_path ||= partial_path || ActionController::RecordIdentifier.partial_path(object, controller.class.controller_path)
0
- path = _paths[_partial_path] ||= find_partial_path(_partial_path)
0
- template = _templates[path] ||= pick_template(path)
0
+ path = find_partial_path(_partial_path)
0
+ template = pick_template(path)
0
           local_assigns[template.counter_name] = index
0
           result = template.render_partial(self, object, local_assigns, as)
0
           index += 1
0
@@ -153,5 +153,6 @@ module ActionView
0
           "_#{partial_path}"
0
         end
0
       end
0
+ memoize :find_partial_path
0
   end
0
 end
...
84
85
86
87
 
88
89
90
...
84
85
86
 
87
88
89
90
0
@@ -84,7 +84,7 @@ module ActionView
0
       # The template will be compiled if the file has not been compiled yet, or
0
       # if local_assigns has a new key, which isn't supported by the compiled code yet.
0
       def recompile?(symbol)
0
- !(frozen? && Base::CompiledTemplates.method_defined?(symbol))
0
+ !(ActionView::PathSet::Path.eager_load_templates? && Base::CompiledTemplates.method_defined?(symbol))
0
       end
0
   end
0
 end
...
30
31
32
33
 
 
34
35
 
 
36
37
38
...
30
31
32
 
33
34
35
36
37
38
39
40
41
0
@@ -30,9 +30,12 @@ uses_mocha 'TestTemplateRecompilation' do
0
       assert_equal "Hello world!", render("test/hello_world.erb")
0
     end
0
 
0
- def test_compiled_template_will_be_recompiled_when_rendered_if_template_is_outside_cache
0
+ def test_compiled_template_will_always_be_recompiled_when_eager_loaded_templates_is_off
0
+ ActionView::PathSet::Path.expects(:eager_load_templates?).times(4).returns(false)
0
       assert_equal 0, @compiled_templates.instance_methods.size
0
       assert_equal "Hello world!", render("#{FIXTURE_LOAD_PATH}/test/hello_world.erb")
0
+ ActionView::Template.any_instance.expects(:compile!).times(3)
0
+ 3.times { assert_equal "Hello world!", render("#{FIXTURE_LOAD_PATH}/test/hello_world.erb") }
0
       assert_equal 1, @compiled_templates.instance_methods.size
0
     end
0
 

Comments

  • michaelklishin Wed Jul 23 19:40:03 -0700 2008

    so… this pretty much means you never run this extremely useful piece of code you added to Rails core, correct?

  • josh Wed Jul 23 22:26:20 -0700 2008

    What never runs?

  • josh Wed Jul 23 22:28:45 -0700 2008

    If you talking about “testing”, it caused a problem in development mode with cache reloading. We didn’t exactly have test coverage for that at the time.

  • michaelklishin Thu Jul 24 03:03:32 -0700 2008

    looks like at the moment in time bc5896e was committed with this problem no production applications were using this uber cool mezmorize feature. How come? It’s so valuable and beats ||= every possible way. Josh, can you explain?

  • nbibler Thu Jul 24 05:47:46 -0700 2008

    I don’t know if it’s just early or what, but I can’t tell if this is supposed to be sarcasm or not. :-\

  • GMFlash Fri Jul 25 16:35:22 -0700 2008

    @michaelklishin: But without abstracting ||= users would have to use the actual Ruby language. Yuck! :)

  • Roman2K Fri Jul 25 20:32:27 -0700 2008

    @GMFlash & michaelklishin:

    What do you have against “memoize”? It doesn’t prevent one from still using ||=, it’s just another way of doing the same thing, a “more declarative” way as stated in the documentation of “memoize”.

    And it has its pluses: it makes the code of the memoized method clearer (lines of code the result of should be cached are not offset next to or underneath the ”@expensive ||=”), and more importantly: it does memoize nil and false results like you would expect.

  • lifo Fri Jul 25 22:09:44 -0700 2008

    ZOMFG

  • lifo Fri Jul 25 22:11:47 -0700 2008

    ZOMFG(&:alias_method_chain)

  • Roman2K Fri Jul 25 22:24:11 -0700 2008

    @lifo: would you care to elaborate?

  • NZKoz Sat Jul 26 02:55:05 -0700 2008

    Michael,

    If you’re not going to add any value with your comments, can I suggest you just don’t bother making them. If you have something useful to add we’d love to hear from you either here or on the mailing list. If you’re just going to troll spouting underinformed opinions based on FUD just save your time and ours and don’t bother.

  • ncr Sat Jul 26 05:19:04 -0700 2008

    I think lifo had on mind that alias_method_chain is the same as memoize in a way: declarative, easier, dry, etc. than aliasing by hand. It’s a pattern, so fleshing it out as a method is a good idea.