Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Made fragment caching in views work for rjs and builder as well (closes

#6642) [zsombor]

git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@8542 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
  • Loading branch information...
commit e2e98ef0b8a575712707e4297c5206e2ed7a7d90 1 parent d5645fd
David Heinemeier Hansson dhh authored
2  actionpack/CHANGELOG
View
@@ -1,5 +1,7 @@
*SVN*
+* Made fragment caching in views work for rjs and builder as well #6642 [zsombor]
+
* Fixed rendering of partials with layout when done from site layout #9209 [antramm]
* Fix atom_feed_helper to comply with the atom spec. Closes #10672 [xaviershay]
32 actionpack/lib/action_controller/caching.rb
View
@@ -371,11 +371,10 @@ def fragment_cache_key(name)
name.is_a?(Hash) ? url_for(name).split("://").last : name
end
- # Called by CacheHelper#cache
- def cache_erb_fragment(block, name = {}, options = nil)
+ def fragment_for(block, name = {}, options = nil) #:nodoc:
unless perform_caching then block.call; return end
- buffer = eval(ActionView::Base.erb_variable, block.binding)
+ buffer = yield
if cache = read_fragment(name, options)
buffer.concat(cache)
@@ -386,6 +385,33 @@ def cache_erb_fragment(block, name = {}, options = nil)
end
end
+ # Called by CacheHelper#cache
+ def cache_rxml_fragment(block, name = {}, options = nil) #:nodoc:
+ fragment_for(block, name, options) do
+ eval('xml.target!', block.binding)
+ end
+ end
+
+ # Called by CacheHelper#cache
+ def cache_rjs_fragment(block, name = {}, options = nil) #:nodoc:
+ fragment_for(block, name, options) do
+ begin
+ debug_mode, ActionView::Base.debug_rjs = ActionView::Base.debug_rjs, false
+ eval('page.to_s', block.binding)
+ ensure
+ ActionView::Base.debug_rjs = debug_mode
+ end
+ end
+ end
+
+ # Called by CacheHelper#cache
+ def cache_erb_fragment(block, name = {}, options = nil) #:nodoc:
+ fragment_for(block, name, options) do
+ eval(ActionView::Base.erb_variable, block.binding)
+ end
+ end
+
+
# Writes <tt>content</tt> to the location signified by <tt>name</tt> (see <tt>expire_fragment</tt> for acceptable formats)
def write_fragment(name, content, options = nil)
return unless perform_caching
16 actionpack/lib/action_view/helpers/cache_helper.rb
View
@@ -32,7 +32,21 @@ module CacheHelper
# <i>Topics listed alphabetically</i>
# <% end %>
def cache(name = {}, &block)
- @controller.cache_erb_fragment(block, name)
+ template_extension = first_render[/\.(\w+)$/, 1].to_sym
+ case template_extension
+ when :erb, :rhtml
+ @controller.cache_erb_fragment(block, name)
+ when :rjs
+ @controller.cache_rjs_fragment(block, name)
+ when :builder, :rxml
+ @controller.cache_rxml_fragment(block, name)
+ else
+ # do a last ditch effort for those brave souls using
+ # different template engines. This should give plugin
+ # writters a simple hook.
+ raise "fragment caching not supported for #{template_extension} files." unless @controller.respond_to?("cache_#{template_extension}_fragment")
+ @controller.send "cache_#{template_extension}_fragment", block, name
+ end
end
end
end
150 actionpack/test/controller/caching_test.rb
View
@@ -25,17 +25,17 @@ def found
def not_found
head :not_found
end
-
+
def custom_path
render :text => "Super soaker"
cache_page("Super soaker", "/index.html")
end
-
+
def expire_custom_path
expire_page("/index.html")
head :ok
end
-
+
def trailing_slash
render :text => "Sneak attack"
end
@@ -95,7 +95,7 @@ def test_should_expire_cache_with_custom_path
get :expire_custom_path
assert !File.exist?("#{FILE_STORE_PATH}/index.html")
end
-
+
def test_should_cache_without_trailing_slash_on_url
@controller.class.cache_page 'cached content', '/page_caching_test/trailing_slash'
assert File.exist?("#{FILE_STORE_PATH}/page_caching_test/trailing_slash.html")
@@ -215,7 +215,7 @@ def test_simple_action_cache
get :index
assert_equal cached_time, @response.body
end
-
+
def test_action_cache_with_custom_cache_path
get :show
cached_time = content_to_cache
@@ -262,9 +262,9 @@ def test_cache_is_scoped_by_subdomain
@request.host = 'jamis.hostname.com'
get :index
jamis_cache = content_to_cache
-
+
reset!
-
+
@request.host = 'david.hostname.com'
get :index
david_cache = content_to_cache
@@ -308,7 +308,7 @@ def test_xml_version_of_resource_is_treated_as_different_cache
assert_equal 'xml', path_object.extension
assert_equal 'example.org/posts/index.xml', path_object.path
end
-
+
def test_correct_content_type_is_returned_for_cache_hit
# run it twice to cache it the first time
get :index, :id => 'content-type.xml'
@@ -341,9 +341,141 @@ def reset!
@controller = ActionCachingTestController.new
@request.host = 'hostname.com'
end
-
+
def assert_cache_exists(path)
full_path = File.join(FILE_STORE_PATH, path + '.cache')
assert File.exist?(full_path), "#{full_path.inspect} does not exist."
end
end
+
+class FragmentCachingTestController < ActionController::Base
+ def some_action; end;
+end
+
+class FragmentCachingTest < Test::Unit::TestCase
+ def setup
+ ActionController::Base.perform_caching = true
+ @store = ActionController::Caching::Fragments::UnthreadedMemoryStore.new
+ ActionController::Base.fragment_cache_store = @store
+ @controller = FragmentCachingTestController.new
+ @params = {:controller => 'posts', :action => 'index'}
+ @request = ActionController::TestRequest.new
+ @response = ActionController::TestResponse.new
+ @controller.params = @params
+ @controller.request = @request
+ @controller.response = @response
+ @controller.send(:initialize_current_url)
+ end
+
+ def test_fragement_cache_key
+ assert_equal 'what a key', @controller.fragment_cache_key('what a key')
+ assert_equal( "test.host/fragment_caching_test/some_action",
+ @controller.fragment_cache_key(:controller => 'fragment_caching_test',:action => 'some_action'))
+ end
+
+ def test_read_fragment__with_caching_enabled
+ @store.write('name', 'value')
+ assert_equal 'value', @controller.read_fragment('name')
+ end
+
+ def test_read_fragment__with_caching_disabled
+ ActionController::Base.perform_caching = false
+ @store.write('name', 'value')
+ assert_nil @controller.read_fragment('name')
+ end
+
+ def test_write_fragment__with_caching_enabled
+ assert_nil @store.read('name')
+ assert_equal 'value', @controller.write_fragment('name', 'value')
+ assert_equal 'value', @store.read('name')
+ end
+
+ def test_write_fragment__with_caching_disabled
+ assert_nil @store.read('name')
+ ActionController::Base.perform_caching = false
+ assert_equal nil, @controller.write_fragment('name', 'value')
+ assert_nil @store.read('name')
+ end
+
+ def test_expire_fragment__with_simple_key
+ @store.write('name', 'value')
+ @controller.expire_fragment 'name'
+ assert_nil @store.read('name')
+ end
+
+ def test_expire_fragment__with__regexp
+ @store.write('name', 'value')
+ @store.write('another_name', 'another_value')
+ @store.write('primalgrasp', 'will not expire ;-)')
+
+ @controller.expire_fragment /name/
+
+ assert_nil @store.read('name')
+ assert_nil @store.read('another_name')
+ assert_equal 'will not expire ;-)', @store.read('primalgrasp')
+ end
+
+ def test_fragment_for__with_disabled_caching
+ ActionController::Base.perform_caching = false
+
+ @store.write('expensive', 'fragment content')
+ fragment_computed = false
+
+ buffer = 'generated till now -> '
+ @controller.fragment_for(Proc.new { fragment_computed = true }, 'expensive') { buffer }
+
+ assert fragment_computed
+ assert_equal 'generated till now -> ', buffer
+ end
+
+
+ def test_fragment_for
+ @store.write('expensive', 'fragment content')
+ fragment_computed = false
+
+ buffer = 'generated till now -> '
+ @controller.fragment_for(Proc.new { fragment_computed = true }, 'expensive') { buffer}
+
+ assert !fragment_computed
+ assert_equal 'generated till now -> fragment content', buffer
+ end
+
+ def test_cache_erb_fragment
+ @store.write('expensive', 'fragment content')
+ _erbout = 'generated till now -> '
+
+ assert_equal( 'generated till now -> fragment content',
+ @controller.cache_erb_fragment(Proc.new{ }, 'expensive'))
+ end
+
+ def test_cache_rxml_fragment
+ @store.write('expensive', 'fragment content')
+ xml = 'generated till now -> '
+ class << xml; def target!; to_s; end; end
+
+ assert_equal( 'generated till now -> fragment content',
+ @controller.cache_rxml_fragment(Proc.new{ }, 'expensive'))
+ end
+
+ def test_cache_rjs_fragment
+ @store.write('expensive', 'fragment content')
+ page = 'generated till now -> '
+
+ assert_equal( 'generated till now -> fragment content',
+ @controller.cache_rjs_fragment(Proc.new{ }, 'expensive'))
+ end
+
+ def test_cache_rjs_fragment_debug_mode_does_not_interfere
+ @store.write('expensive', 'fragment content')
+ page = 'generated till now -> '
+
+ begin
+ debug_mode, ActionView::Base.debug_rjs = ActionView::Base.debug_rjs, true
+ assert_equal( 'generated till now -> fragment content',
+ @controller.cache_rjs_fragment(Proc.new{ }, 'expensive'))
+ assert ActionView::Base.debug_rjs
+ ensure
+ ActionView::Base.debug_rjs = debug_mode
+ end
+ end
+end
Please sign in to comment.
Something went wrong with that request. Please try again.