aboutsummaryrefslogtreecommitdiffstats
path: root/actionview
diff options
context:
space:
mode:
Diffstat (limited to 'actionview')
-rw-r--r--actionview/CHANGELOG.md5
-rw-r--r--actionview/lib/action_view/digestor.rb2
-rw-r--r--actionview/lib/action_view/helpers/date_helper.rb23
-rw-r--r--actionview/lib/action_view/lookup_context.rb2
-rw-r--r--actionview/lib/action_view/renderer/partial_renderer.rb2
-rw-r--r--actionview/lib/action_view/rendering.rb2
-rw-r--r--actionview/lib/action_view/template/handlers/erb.rb2
-rw-r--r--actionview/lib/action_view/template/resolver.rb20
-rw-r--r--actionview/lib/action_view/view_paths.rb4
-rw-r--r--actionview/test/template/template_test.rb30
10 files changed, 73 insertions, 19 deletions
diff --git a/actionview/CHANGELOG.md b/actionview/CHANGELOG.md
index 7b6008d5ed..fe47fb47fd 100644
--- a/actionview/CHANGELOG.md
+++ b/actionview/CHANGELOG.md
@@ -1,3 +1,8 @@
+* Improve detection of partial templates eligible for collection caching,
+ now allowing multi-line comments at the beginning of the template file.
+
+ *Dov Murik*
+
* Raise an ArgumentError when a false value for `include_blank` is passed to a
required select field (to comply with the HTML5 spec).
diff --git a/actionview/lib/action_view/digestor.rb b/actionview/lib/action_view/digestor.rb
index b29eb48425..df8059d04e 100644
--- a/actionview/lib/action_view/digestor.rb
+++ b/actionview/lib/action_view/digestor.rb
@@ -12,7 +12,7 @@ module ActionView
# Supported options:
#
# * <tt>name</tt> - Template name
- # * <tt>finder</tt> - An instance of ActionView::LookupContext
+ # * <tt>finder</tt> - An instance of <tt>ActionView::LookupContext</tt>
# * <tt>dependencies</tt> - An array of dependent views
# * <tt>partial</tt> - Specifies whether the template is a partial
def digest(options)
diff --git a/actionview/lib/action_view/helpers/date_helper.rb b/actionview/lib/action_view/helpers/date_helper.rb
index 394e20ff2b..9c8edc69a9 100644
--- a/actionview/lib/action_view/helpers/date_helper.rb
+++ b/actionview/lib/action_view/helpers/date_helper.rb
@@ -68,6 +68,27 @@ module ActionView
# distance_of_time_in_words(from_time, to_time, include_seconds: true) # => about 6 years
# distance_of_time_in_words(to_time, from_time, include_seconds: true) # => about 6 years
# distance_of_time_in_words(Time.now, Time.now) # => less than a minute
+ #
+ # With the <tt>scope</tt> option, you can define a custom scope for Rails
+ # to lookup the translation.
+ #
+ # For example you can define the following in your locale (e.g. en.yml).
+ #
+ # datetime:
+ # distance_in_words:
+ # short:
+ # about_x_hours:
+ # one: 'an hour'
+ # other: '%{count} hours'
+ #
+ # See https://github.com/svenfuchs/rails-i18n/blob/master/rails/locale/en.yml
+ # for more examples.
+ #
+ # Which will then result in the following:
+ #
+ # from_time = Time.now
+ # distance_of_time_in_words(from_time, from_time + 50.minutes, scope: 'datetime.distance_in_words.short') # => "an hour"
+ # distance_of_time_in_words(from_time, from_time + 3.hours, scope: 'datetime.distance_in_words.short') # => "3 hours"
def distance_of_time_in_words(from_time, to_time = 0, options = {})
options = {
scope: :'datetime.distance_in_words'
@@ -464,7 +485,7 @@ module ActionView
# The <tt>datetime</tt> can be either a +Time+ or +DateTime+ object or an integer.
# Override the field name using the <tt>:field_name</tt> option, 'second' by default.
#
- # my_time = Time.now + 16.minutes
+ # my_time = Time.now + 16.seconds
#
# # Generates a select field for seconds that defaults to the seconds for the time in my_time.
# select_second(my_time)
diff --git a/actionview/lib/action_view/lookup_context.rb b/actionview/lib/action_view/lookup_context.rb
index 4452dcfed5..817b30dd2f 100644
--- a/actionview/lib/action_view/lookup_context.rb
+++ b/actionview/lib/action_view/lookup_context.rb
@@ -6,7 +6,7 @@ require 'action_view/template/resolver'
module ActionView
# = Action View Lookup Context
#
- # LookupContext is the object responsible to hold all information required to lookup
+ # <tt>LookupContext</tt> is the object responsible to hold all information required to lookup
# templates, i.e. view paths and details. The LookupContext is also responsible to
# generate a key, given to view paths, used in the resolver cache lookup. Since
# this key is generated just once during the request, it speeds up all cache accesses.
diff --git a/actionview/lib/action_view/renderer/partial_renderer.rb b/actionview/lib/action_view/renderer/partial_renderer.rb
index b751bca31e..780fdabbd1 100644
--- a/actionview/lib/action_view/renderer/partial_renderer.rb
+++ b/actionview/lib/action_view/renderer/partial_renderer.rb
@@ -348,8 +348,6 @@ module ActionView
content
end
- private
-
# Sets up instance variables needed for rendering a partial. This method
# finds the options and details and extracts them. The method also contains
# logic that handles the type of object passed in as the partial.
diff --git a/actionview/lib/action_view/rendering.rb b/actionview/lib/action_view/rendering.rb
index 1e8e7415d1..91b7e845d6 100644
--- a/actionview/lib/action_view/rendering.rb
+++ b/actionview/lib/action_view/rendering.rb
@@ -59,7 +59,7 @@ module ActionView
@_view_context_class ||= self.class.view_context_class
end
- # An instance of a view class. The default view class is ActionView::Base
+ # An instance of a view class. The default view class is ActionView::Base.
#
# The view class must have the following methods:
# View.new[lookup_context, assigns, controller]
diff --git a/actionview/lib/action_view/template/handlers/erb.rb b/actionview/lib/action_view/template/handlers/erb.rb
index 88a8570706..da96347e4d 100644
--- a/actionview/lib/action_view/template/handlers/erb.rb
+++ b/actionview/lib/action_view/template/handlers/erb.rb
@@ -138,7 +138,7 @@ module ActionView
#
# <% cache notification.event do %> # => nil
def resource_cache_call_pattern
- /\A(?:<%#.*%>\n?)?<% cache\(?\s*(\w+\.?)/
+ /\A(?:<%#.*%>)*\s*<%\s*cache\(?\s*(\w+)[\s\)]/m
end
private
diff --git a/actionview/lib/action_view/template/resolver.rb b/actionview/lib/action_view/template/resolver.rb
index 955118a554..2b00b0303d 100644
--- a/actionview/lib/action_view/template/resolver.rb
+++ b/actionview/lib/action_view/template/resolver.rb
@@ -181,9 +181,9 @@ module ActionView
def query(path, details, formats)
query = build_query(path, details)
- template_paths = find_template_paths query
+ template_paths = find_template_paths(query)
- template_paths.map { |template|
+ template_paths.map do |template|
handler, format, variant = extract_handler_and_format_and_variant(template, formats)
contents = File.binread(template)
@@ -193,29 +193,29 @@ module ActionView
:variant => variant,
:updated_at => mtime(template)
)
- }
+ end
end
def find_template_paths(query)
- Dir[query].reject { |filename|
+ Dir[query].reject do |filename|
File.directory?(filename) ||
# deals with case-insensitive file systems.
!File.fnmatch(query, filename, File::FNM_EXTGLOB)
- }
+ end
end
# Helper for building query glob string based on resolver's pattern.
def build_query(path, details)
query = @pattern.dup
- prefix = path.prefix.empty? ? "" : "#{escape_entry(path.prefix)}\\1"
- query.gsub!(/\:prefix(\/)?/, prefix)
+ prefix = path.prefix.empty? ? '' : "#{escape_entry(path.prefix)}\\1"
+ query.gsub!(/:prefix(\/)?/, prefix)
partial = escape_entry(path.partial? ? "_#{path.name}" : path.name)
- query.gsub!(/\:action/, partial)
+ query.gsub!(/:action/, partial)
details.each do |ext, variants|
- query.gsub!(/\:#{ext}/, "{#{variants.compact.uniq.join(',')}}")
+ query.gsub!(/:#{ext}/, "{#{variants.compact.uniq.join(',')}}")
end
File.expand_path(query, @path)
@@ -234,7 +234,7 @@ module ActionView
# from the path, or the handler, we should return the array of formats given
# to the resolver.
def extract_handler_and_format_and_variant(path, default_formats)
- pieces = File.basename(path).split(".")
+ pieces = File.basename(path).split('.')
pieces.shift
extension = pieces.pop
diff --git a/actionview/lib/action_view/view_paths.rb b/actionview/lib/action_view/view_paths.rb
index 492f67f45d..ebca598337 100644
--- a/actionview/lib/action_view/view_paths.rb
+++ b/actionview/lib/action_view/view_paths.rb
@@ -36,8 +36,8 @@ module ActionView
self.class._prefixes
end
- # LookupContext is the object responsible to hold all information required to lookup
- # templates, i.e. view paths and details. Check ActionView::LookupContext for more
+ # <tt>LookupContext</tt> is the object responsible to hold all information required to lookup
+ # templates, i.e. view paths and details. Check <tt>ActionView::LookupContext</tt> for more
# information.
def lookup_context
@_lookup_context ||=
diff --git a/actionview/test/template/template_test.rb b/actionview/test/template/template_test.rb
index aae6a9aa09..d17034e88f 100644
--- a/actionview/test/template/template_test.rb
+++ b/actionview/test/template/template_test.rb
@@ -190,6 +190,36 @@ class TestERBTemplate < ActiveSupport::TestCase
assert_match(/\xFC/, e.message)
end
+ def test_not_eligible_for_collection_caching_without_cache_call
+ [
+ "<%= 'Hello' %>",
+ "<% cache_customer = 42 %>",
+ "<% cache customer.name 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
+ [
+ "<% cache customer do %><% end %>",
+ "<% cache(customer) do %><% end %>",
+ "<% cache( customer) do %><% end %>",
+ "<% cache( customer ) do %><% end %>",
+ "<%cache customer do %><% end %>",
+ "<% cache customer do %><% end %>",
+ " <% cache customer do %>\n<% end %>\n",
+ "<%# 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 %>"
+ ].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"
+ end
+ end
+
def with_external_encoding(encoding)
old = Encoding.default_external
Encoding::Converter.new old, encoding if old != encoding