mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Support explicit defintion of resouce name for collection caching.
If a template includes `# Template Collection: ...` anywhere in its source, that name will be used as the cache name for the partial that is rendered for the collection. This allows users to enable collection caching even if the template doesn't start with `<% cache ... do %>`. Moreover, the `# Template Collection: ...` notation is recognized in all template types (and template types other than ERB can define a resource_cache_call_pattern method to allow the `cache ... do` pattern to be recognized too).
This commit is contained in:
parent
062cbd18dd
commit
5a41d00455
5 changed files with 47 additions and 9 deletions
|
@ -1,3 +1,8 @@
|
|||
* Allow defining explicit collection caching using a `# Template Collection: ...`
|
||||
directive inside templates.
|
||||
|
||||
*Dov Murik*
|
||||
|
||||
* Asset helpers raise `ArgumentError` when `nil` is passed as a source.
|
||||
|
||||
*Anton Kolomiychuk*
|
||||
|
|
|
@ -137,6 +137,21 @@ module ActionView
|
|||
# The automatic cache multi read can be turned off like so:
|
||||
#
|
||||
# <%= render @notifications, cache: false %>
|
||||
#
|
||||
# === Explicit Collection Caching
|
||||
#
|
||||
# If the partial template doesn't start with a clean cache call as
|
||||
# mentioned above, you can still benefit from collection caching by
|
||||
# adding a special comment format anywhere in the template, like:
|
||||
#
|
||||
# <%# Template Collection: notification %>
|
||||
# <% my_helper_that_calls_cache(some_arg, notification) do %>
|
||||
# <%= notification.name %>
|
||||
# <% end %>
|
||||
#
|
||||
# The pattern used to match these is <tt>/# Template Collection: (\S+)/</tt>,
|
||||
# so it's important that you type it out just so.
|
||||
# You can only declare one collection in a partial template file.
|
||||
def cache(name = {}, options = {}, &block)
|
||||
if controller.respond_to?(:perform_caching) && controller.perform_caching
|
||||
safe_concat(fragment_for(cache_fragment_name(name, options), options, &block))
|
||||
|
|
|
@ -130,7 +130,7 @@ module ActionView
|
|||
@source = source
|
||||
@identifier = identifier
|
||||
@handler = handler
|
||||
@cache_name = extract_resource_cache_call_name
|
||||
@cache_name = extract_resource_cache_name
|
||||
@compiled = false
|
||||
@original_encoding = nil
|
||||
@locals = details[:locals] || []
|
||||
|
@ -351,9 +351,18 @@ module ActionView
|
|||
ActiveSupport::Notifications.instrument("#{action}.action_view", payload, &block)
|
||||
end
|
||||
|
||||
def extract_resource_cache_call_name
|
||||
$1 if @handler.respond_to?(:resource_cache_call_pattern) &&
|
||||
@source =~ @handler.resource_cache_call_pattern
|
||||
EXPLICIT_COLLECTION = /# Template Collection: (?<resource_name>\w+)/
|
||||
|
||||
def extract_resource_cache_name
|
||||
if match = @source.match(EXPLICIT_COLLECTION) || resource_cache_call_match
|
||||
match[:resource_name]
|
||||
end
|
||||
end
|
||||
|
||||
def resource_cache_call_match
|
||||
if @handler.respond_to?(:resource_cache_call_pattern)
|
||||
@source.match(@handler.resource_cache_call_pattern)
|
||||
end
|
||||
end
|
||||
|
||||
def inferred_cache_name
|
||||
|
|
|
@ -125,7 +125,7 @@ module ActionView
|
|||
|
||||
# Returns Regexp to extract a cached resource's name from a cache call at the
|
||||
# first line of a template.
|
||||
# The extracted cache name is expected in $1.
|
||||
# The extracted cache name is captured as :resource_name.
|
||||
#
|
||||
# <% cache notification do %> # => notification
|
||||
#
|
||||
|
@ -138,7 +138,14 @@ module ActionView
|
|||
#
|
||||
# <% cache notification.event do %> # => nil
|
||||
def resource_cache_call_pattern
|
||||
/\A(?:<%#.*%>)*\s*<%\s*cache\(?\s*(\w+)[\s\)]/m
|
||||
/\A
|
||||
(?:<%\#.*%>)* # optional initial comment
|
||||
\s* # followed by optional spaces or newlines
|
||||
<%\s*cache[\(\s] # followed by an ERB call to cache
|
||||
\s* # followed by optional spaces or newlines
|
||||
(?<resource_name>\w+) # capture the cache call argument as :resource_name
|
||||
[\s\)] # followed by a space or close paren
|
||||
/xm
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -194,14 +194,15 @@ class TestERBTemplate < ActiveSupport::TestCase
|
|||
[
|
||||
"<%= 'Hello' %>",
|
||||
"<% cache_customer = 42 %>",
|
||||
"<% cache customer.name do %><% end %>"
|
||||
"<% cache customer.name do %><% end %>",
|
||||
"<% my_cache customer do %><% end %>"
|
||||
].each do |body|
|
||||
template = new_template(body, virtual_path: "test/foo/_customer")
|
||||
assert_not template.eligible_for_collection_caching?, "Template #{body.inspect} should not be eligible for collection caching"
|
||||
end
|
||||
end
|
||||
|
||||
def test_eligible_for_collection_caching_with_cache_call
|
||||
def test_eligible_for_collection_caching_with_cache_call_or_explicit
|
||||
[
|
||||
"<% cache customer do %><% end %>",
|
||||
"<% cache(customer) do %><% end %>",
|
||||
|
@ -213,7 +214,8 @@ class TestERBTemplate < ActiveSupport::TestCase
|
|||
"<%# comment %><% cache customer do %><% end %>",
|
||||
"<%# comment %>\n<% cache customer do %><% end %>",
|
||||
"<%# comment\n line 2\n line 3 %>\n<% cache customer do %><% end %>",
|
||||
"<%# comment 1 %>\n<%# comment 2 %>\n<% cache customer do %><% end %>"
|
||||
"<%# comment 1 %>\n<%# comment 2 %>\n<% cache customer do %><% end %>",
|
||||
"<%# comment 1 %>\n<%# Template Collection: customer %>\n<% my_cache customer do %><% end %>"
|
||||
].each do |body|
|
||||
template = new_template(body, virtual_path: "test/foo/_customer")
|
||||
assert template.eligible_for_collection_caching?, "Template #{body.inspect} should be eligible for collection caching"
|
||||
|
|
Loading…
Reference in a new issue