diff options
Diffstat (limited to 'actionview/lib')
10 files changed, 76 insertions, 35 deletions
diff --git a/actionview/lib/action_view/helpers/asset_url_helper.rb b/actionview/lib/action_view/helpers/asset_url_helper.rb index ef4a6c98c0..b19dc25025 100644 --- a/actionview/lib/action_view/helpers/asset_url_helper.rb +++ b/actionview/lib/action_view/helpers/asset_url_helper.rb @@ -121,6 +121,8 @@ module ActionView # asset_path "application", type: :stylesheet # => /assets/application.css # asset_path "http://www.example.com/js/xmlhr.js" # => http://www.example.com/js/xmlhr.js def asset_path(source, options = {}) + raise ArgumentError, "nil is not a valid asset source" if source.nil? + source = source.to_s return "" unless source.present? return source if source =~ URI_REGEXP diff --git a/actionview/lib/action_view/helpers/cache_helper.rb b/actionview/lib/action_view/helpers/cache_helper.rb index 72e2aa1807..797d029317 100644 --- a/actionview/lib/action_view/helpers/cache_helper.rb +++ b/actionview/lib/action_view/helpers/cache_helper.rb @@ -137,7 +137,22 @@ module ActionView # The automatic cache multi read can be turned off like so: # # <%= render @notifications, cache: false %> - def cache(name = {}, options = nil, &block) + # + # === 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)) else @@ -153,7 +168,7 @@ module ActionView # <b>All the topics on this project</b> # <%= render project.topics %> # <% end %> - def cache_if(condition, name = {}, options = nil, &block) + def cache_if(condition, name = {}, options = {}, &block) if condition cache(name, options, &block) else @@ -169,22 +184,23 @@ module ActionView # <b>All the topics on this project</b> # <%= render project.topics %> # <% end %> - def cache_unless(condition, name = {}, options = nil, &block) + def cache_unless(condition, name = {}, options = {}, &block) cache_if !condition, name, options, &block end # This helper returns the name of a cache key for a given fragment cache - # call. By supplying skip_digest: true to cache, the digestion of cache + # call. By supplying +skip_digest:+ true to cache, the digestion of cache # fragments can be manually bypassed. This is useful when cache fragments # cannot be manually expired unless you know the exact key which is the # case when using memcached. - def cache_fragment_name(name = {}, options = nil) - skip_digest = options && options[:skip_digest] - + # + # The digest will be generated using +virtual_path:+ if it is provided. + # + def cache_fragment_name(name = {}, skip_digest: nil, virtual_path: nil) if skip_digest name else - fragment_name_with_digest(name) + fragment_name_with_digest(name, virtual_path) end end @@ -198,10 +214,11 @@ module ActionView private - def fragment_name_with_digest(name) #:nodoc: - if @virtual_path + def fragment_name_with_digest(name, virtual_path) #:nodoc: + virtual_path ||= @virtual_path + if virtual_path names = Array(name.is_a?(Hash) ? controller.url_for(name).split("://").last : name) - digest = Digestor.digest name: @virtual_path, finder: lookup_context, dependencies: view_cache_dependencies + digest = Digestor.digest name: virtual_path, finder: lookup_context, dependencies: view_cache_dependencies [ *names, digest ] else diff --git a/actionview/lib/action_view/helpers/date_helper.rb b/actionview/lib/action_view/helpers/date_helper.rb index 0633213d5e..9c8edc69a9 100644 --- a/actionview/lib/action_view/helpers/date_helper.rb +++ b/actionview/lib/action_view/helpers/date_helper.rb @@ -69,8 +69,8 @@ module ActionView # 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> you can define a custom scope for Rails lookup - # the translation. + # 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). # @@ -78,8 +78,8 @@ module ActionView # distance_in_words: # short: # about_x_hours: - # one: 1 hr - # other: '%{count} hr' + # one: 'an hour' + # other: '%{count} hours' # # See https://github.com/svenfuchs/rails-i18n/blob/master/rails/locale/en.yml # for more examples. @@ -87,8 +87,8 @@ module ActionView # 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') # => 1 hr - # distance_of_time_in_words(from_time, from_time + 3.hours, scope: 'datetime.distance_in_words.short') # => 3 hr + # 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' diff --git a/actionview/lib/action_view/helpers/form_options_helper.rb b/actionview/lib/action_view/helpers/form_options_helper.rb index 1b7b188d65..8e729b3c39 100644 --- a/actionview/lib/action_view/helpers/form_options_helper.rb +++ b/actionview/lib/action_view/helpers/form_options_helper.rb @@ -35,8 +35,8 @@ module ActionView # <select name="post[person_id]" id="post_person_id"> # <option value="">None</option> # <option value="1">David</option> - # <option value="2" selected="selected">Sam</option> - # <option value="3">Tobias</option> + # <option value="2" selected="selected">Eileen</option> + # <option value="3">Rafael</option> # </select> # # * <tt>:prompt</tt> - set to true or a prompt string. When the select element doesn't have a value yet, this prepends an option with a generic prompt -- "Please select" -- or the given prompt string. @@ -48,8 +48,8 @@ module ActionView # <select name="post[person_id]" id="post_person_id"> # <option value="">Select Person</option> # <option value="1">David</option> - # <option value="2">Sam</option> - # <option value="3">Tobias</option> + # <option value="2">Eileen</option> + # <option value="3">Rafael</option> # </select> # # * <tt>:index</tt> - like the other form helpers, +select+ can accept an <tt>:index</tt> option to manually set the ID used in the resulting output. Unlike other helpers, +select+ expects this @@ -112,8 +112,8 @@ module ActionView # <select name="post[person_id]" id="post_person_id"> # <option value=""></option> # <option value="1" selected="selected">David</option> - # <option value="2">Sam</option> - # <option value="3">Tobias</option> + # <option value="2">Eileen</option> + # <option value="3">Rafael</option> # </select> # # assuming the associated person has ID 1. diff --git a/actionview/lib/action_view/helpers/text_helper.rb b/actionview/lib/action_view/helpers/text_helper.rb index c216d4401f..6a3d01667d 100644 --- a/actionview/lib/action_view/helpers/text_helper.rb +++ b/actionview/lib/action_view/helpers/text_helper.rb @@ -206,6 +206,11 @@ module ActionView # +plural+ is supplied, it will use that when count is > 1, otherwise # it will use the Inflector to determine the plural form. # + # If passed an optional +locale:+ parameter, the word will be pluralized + # using rules defined for that language (you must define your own + # inflection rules for languages other than English). See + # ActiveSupport::Inflector.pluralize + # # pluralize(1, 'person') # # => 1 person # @@ -217,11 +222,14 @@ module ActionView # # pluralize(0, 'person') # # => 0 people - def pluralize(count, singular, plural = nil) + # + # pluralize(2, 'Person', locale: :de) + # # => 2 Personen + def pluralize(count, singular, plural = nil, locale: nil) word = if (count == 1 || count =~ /^1(\.0+)?$/) singular else - plural || singular.pluralize + plural || singular.pluralize(locale) end "#{count || 0} #{word}" 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/renderer/partial_renderer/collection_caching.rb b/actionview/lib/action_view/renderer/partial_renderer/collection_caching.rb index c8268e226e..1147963882 100644 --- a/actionview/lib/action_view/renderer/partial_renderer/collection_caching.rb +++ b/actionview/lib/action_view/renderer/partial_renderer/collection_caching.rb @@ -51,7 +51,7 @@ module ActionView end def expanded_cache_key(key) - key = @view.fragment_cache_key(@view.cache_fragment_name(key)) + key = @view.fragment_cache_key(@view.cache_fragment_name(key, virtual_path: @template.virtual_path)) key.frozen? ? key.dup : key # #read_multi & #write may require mutability, Dalli 2.6.0. end diff --git a/actionview/lib/action_view/template.rb b/actionview/lib/action_view/template.rb index 377ceb534a..d8585514d5 100644 --- a/actionview/lib/action_view/template.rb +++ b/actionview/lib/action_view/template.rb @@ -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 diff --git a/actionview/lib/action_view/template/handlers/erb.rb b/actionview/lib/action_view/template/handlers/erb.rb index 88a8570706..1f8459c24b 100644 --- a/actionview/lib/action_view/template/handlers/erb.rb +++ b/actionview/lib/action_view/template/handlers/erb.rb @@ -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(?:<%#.*%>\n?)?<% cache\(?\s*(\w+\.?)/ + /\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 diff --git a/actionview/lib/action_view/test_case.rb b/actionview/lib/action_view/test_case.rb index 06810ad14d..b4f36c1f78 100644 --- a/actionview/lib/action_view/test_case.rb +++ b/actionview/lib/action_view/test_case.rb @@ -24,7 +24,7 @@ module ActionView def initialize super self.class.controller_path = "" - @request = ActionController::TestRequest.new + @request = ActionController::TestRequest.create @response = ActionController::TestResponse.new @request.env.delete('PATH_INFO') |