diff options
Diffstat (limited to 'actionview/lib/action_view')
23 files changed, 175 insertions, 88 deletions
diff --git a/actionview/lib/action_view/base.rb b/actionview/lib/action_view/base.rb index 5253ef7b0c..40d5ed36a1 100644 --- a/actionview/lib/action_view/base.rb +++ b/actionview/lib/action_view/base.rb @@ -3,7 +3,6 @@ require "active_support/core_ext/module/attr_internal" require "active_support/core_ext/module/attribute_accessors" require "active_support/ordered_options" -require "active_support/deprecation" require "action_view/log_subscriber" require "action_view/helpers" require "action_view/context" diff --git a/actionview/lib/action_view/digestor.rb b/actionview/lib/action_view/digestor.rb index 97a6da3634..cdf436ccae 100644 --- a/actionview/lib/action_view/digestor.rb +++ b/actionview/lib/action_view/digestor.rb @@ -9,10 +9,11 @@ module ActionView class << self # Supported options: # - # * <tt>name</tt> - Template name - # * <tt>finder</tt> - An instance of <tt>ActionView::LookupContext</tt> - # * <tt>dependencies</tt> - An array of dependent views - def digest(name:, format:, finder:, dependencies: nil) + # * <tt>name</tt> - Template name + # * <tt>format</tt> - Template format + # * <tt>finder</tt> - An instance of <tt>ActionView::LookupContext</tt> + # * <tt>dependencies</tt> - An array of dependent views + def digest(name:, format: nil, finder:, dependencies: nil) if dependencies.nil? || dependencies.empty? cache_key = "#{name}.#{format}" else diff --git a/actionview/lib/action_view/helpers/asset_tag_helper.rb b/actionview/lib/action_view/helpers/asset_tag_helper.rb index 59d70a1dc4..1e1d97fe75 100644 --- a/actionview/lib/action_view/helpers/asset_tag_helper.rb +++ b/actionview/lib/action_view/helpers/asset_tag_helper.rb @@ -3,7 +3,6 @@ require "active_support/core_ext/array/extract_options" require "active_support/core_ext/hash/keys" require "active_support/core_ext/object/inclusion" -require "active_support/core_ext/object/try" require "action_view/helpers/asset_url_helper" require "action_view/helpers/tag_helper" @@ -268,7 +267,7 @@ module ActionView def preload_link_tag(source, options = {}) href = asset_path(source, skip_pipeline: options.delete(:skip_pipeline)) extname = File.extname(source).downcase.delete(".") - mime_type = options.delete(:type) || Template::Types[extname].try(:to_s) + mime_type = options.delete(:type) || Template::Types[extname]&.to_s as_type = options.delete(:as) || resolve_link_as(extname, mime_type) crossorigin = options.delete(:crossorigin) crossorigin = "anonymous" if crossorigin == true || (crossorigin.blank? && as_type == "font") diff --git a/actionview/lib/action_view/helpers/asset_url_helper.rb b/actionview/lib/action_view/helpers/asset_url_helper.rb index cc62783d60..295f945325 100644 --- a/actionview/lib/action_view/helpers/asset_url_helper.rb +++ b/actionview/lib/action_view/helpers/asset_url_helper.rb @@ -133,6 +133,8 @@ module ActionView # which is implemented by sprockets-rails. # # asset_path("application.js") # => "/assets/application-60aa4fdc5cea14baf5400fba1abf4f2a46a5166bad4772b1effe341570f07de9.js" + # asset_path('application.js', host: 'example.com') # => "//example.com/assets/application.js" + # asset_path("application.js", host: 'example.com', protocol: 'https') # => "https://example.com/assets/application.js" # # === Without the asset pipeline (<tt>skip_pipeline: true</tt>) # diff --git a/actionview/lib/action_view/helpers/form_options_helper.rb b/actionview/lib/action_view/helpers/form_options_helper.rb index a7747456a4..cf8f7de931 100644 --- a/actionview/lib/action_view/helpers/form_options_helper.rb +++ b/actionview/lib/action_view/helpers/form_options_helper.rb @@ -566,9 +566,10 @@ module ActionView # an ActiveSupport::TimeZone. # # By default, +model+ is the ActiveSupport::TimeZone constant (which can - # be obtained in Active Record as a value object). The only requirement - # is that the +model+ parameter be an object that responds to +all+, and - # returns an array of objects that represent time zones. + # be obtained in Active Record as a value object). The +model+ parameter + # must respond to +all+ and return an array of objects that represent time + # zones; each object must respond to +name+. If a Regexp is given it will + # attempt to match the zones using <code>match?</code> method. # # NOTE: Only the option tags are returned, you have to wrap this call in # a regular HTML select tag. @@ -580,7 +581,7 @@ module ActionView if priority_zones if priority_zones.is_a?(Regexp) - priority_zones = zones.select { |z| z =~ priority_zones } + priority_zones = zones.select { |z| z.match?(priority_zones) } end zone_options.safe_concat options_for_select(convert_zones[priority_zones], selected) diff --git a/actionview/lib/action_view/helpers/sanitize_helper.rb b/actionview/lib/action_view/helpers/sanitize_helper.rb index f4fa133f55..d6d0635911 100644 --- a/actionview/lib/action_view/helpers/sanitize_helper.rb +++ b/actionview/lib/action_view/helpers/sanitize_helper.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true -require "active_support/core_ext/object/try" require "rails-html-sanitizer" +require "active_support/deprecation" module ActionView # = Action View Sanitize Helpers @@ -17,7 +17,7 @@ module ActionView # ASCII, and hex character references to work around these protocol filters. # All special characters will be escaped. # - # The default sanitizer is Rails::Html::WhiteListSanitizer. See {Rails HTML + # The default sanitizer is Rails::Html::SafeListSanitizer. See {Rails HTML # Sanitizers}[https://github.com/rails/rails-html-sanitizer] for more information. # # Custom sanitization rules can also be provided. @@ -80,12 +80,12 @@ module ActionView # config.action_view.sanitized_allowed_tags = ['strong', 'em', 'a'] # config.action_view.sanitized_allowed_attributes = ['href', 'title'] def sanitize(html, options = {}) - self.class.white_list_sanitizer.sanitize(html, options).try(:html_safe) + self.class.safe_list_sanitizer.sanitize(html, options)&.html_safe end # Sanitizes a block of CSS code. Used by +sanitize+ when it comes across a style attribute. def sanitize_css(style) - self.class.white_list_sanitizer.sanitize_css(style) + self.class.safe_list_sanitizer.sanitize_css(style) end # Strips all HTML tags from +html+, including comments and special characters. @@ -123,20 +123,14 @@ module ActionView end module ClassMethods #:nodoc: - attr_writer :full_sanitizer, :link_sanitizer, :white_list_sanitizer - - # Vendors the full, link and white list sanitizers. - # Provided strictly for compatibility and can be removed in Rails 6. - def sanitizer_vendor - Rails::Html::Sanitizer - end + attr_writer :full_sanitizer, :link_sanitizer, :safe_list_sanitizer def sanitized_allowed_tags - sanitizer_vendor.white_list_sanitizer.allowed_tags + safe_list_sanitizer.allowed_tags end def sanitized_allowed_attributes - sanitizer_vendor.white_list_sanitizer.allowed_attributes + safe_list_sanitizer.allowed_attributes end # Gets the Rails::Html::FullSanitizer instance used by +strip_tags+. Replace with @@ -145,9 +139,8 @@ module ActionView # class Application < Rails::Application # config.action_view.full_sanitizer = MySpecialSanitizer.new # end - # def full_sanitizer - @full_sanitizer ||= sanitizer_vendor.full_sanitizer.new + @full_sanitizer ||= Rails::Html::Sanitizer.full_sanitizer.new end # Gets the Rails::Html::LinkSanitizer instance used by +strip_links+. @@ -156,20 +149,18 @@ module ActionView # class Application < Rails::Application # config.action_view.link_sanitizer = MySpecialSanitizer.new # end - # def link_sanitizer - @link_sanitizer ||= sanitizer_vendor.link_sanitizer.new + @link_sanitizer ||= Rails::Html::Sanitizer.link_sanitizer.new end - # Gets the Rails::Html::WhiteListSanitizer instance used by sanitize and +sanitize_css+. + # Gets the Rails::Html::SafeListSanitizer instance used by sanitize and +sanitize_css+. # Replace with any object that responds to +sanitize+. # # class Application < Rails::Application - # config.action_view.white_list_sanitizer = MySpecialSanitizer.new + # config.action_view.safe_list_sanitizer = MySpecialSanitizer.new # end - # - def white_list_sanitizer - @white_list_sanitizer ||= sanitizer_vendor.white_list_sanitizer.new + def safe_list_sanitizer + @safe_list_sanitizer ||= Rails::Html::Sanitizer.safe_list_sanitizer.new end end end diff --git a/actionview/lib/action_view/helpers/tags/date_field.rb b/actionview/lib/action_view/helpers/tags/date_field.rb index ceaabfa99c..9cdfc6991f 100644 --- a/actionview/lib/action_view/helpers/tags/date_field.rb +++ b/actionview/lib/action_view/helpers/tags/date_field.rb @@ -6,7 +6,7 @@ module ActionView class DateField < DatetimeField # :nodoc: private def format_date(value) - value.try(:strftime, "%Y-%m-%d") + value&.strftime("%Y-%m-%d") end end end diff --git a/actionview/lib/action_view/helpers/tags/datetime_local_field.rb b/actionview/lib/action_view/helpers/tags/datetime_local_field.rb index 8908bf9948..f0834ac6ce 100644 --- a/actionview/lib/action_view/helpers/tags/datetime_local_field.rb +++ b/actionview/lib/action_view/helpers/tags/datetime_local_field.rb @@ -12,7 +12,7 @@ module ActionView private def format_date(value) - value.try(:strftime, "%Y-%m-%dT%T") + value&.strftime("%Y-%m-%dT%T") end end end diff --git a/actionview/lib/action_view/helpers/tags/month_field.rb b/actionview/lib/action_view/helpers/tags/month_field.rb index 463866a181..b582bb4f79 100644 --- a/actionview/lib/action_view/helpers/tags/month_field.rb +++ b/actionview/lib/action_view/helpers/tags/month_field.rb @@ -6,7 +6,7 @@ module ActionView class MonthField < DatetimeField # :nodoc: private def format_date(value) - value.try(:strftime, "%Y-%m") + value&.strftime("%Y-%m") end end end diff --git a/actionview/lib/action_view/helpers/tags/time_field.rb b/actionview/lib/action_view/helpers/tags/time_field.rb index e74c578db9..e5e0b84891 100644 --- a/actionview/lib/action_view/helpers/tags/time_field.rb +++ b/actionview/lib/action_view/helpers/tags/time_field.rb @@ -6,7 +6,7 @@ module ActionView class TimeField < DatetimeField # :nodoc: private def format_date(value) - value.try(:strftime, "%T.%L") + value&.strftime("%T.%L") end end end diff --git a/actionview/lib/action_view/helpers/tags/week_field.rb b/actionview/lib/action_view/helpers/tags/week_field.rb index 5a403ed91d..7828a3149f 100644 --- a/actionview/lib/action_view/helpers/tags/week_field.rb +++ b/actionview/lib/action_view/helpers/tags/week_field.rb @@ -6,7 +6,7 @@ module ActionView class WeekField < DatetimeField # :nodoc: private def format_date(value) - value.try(:strftime, "%Y-W%V") + value&.strftime("%Y-W%V") end end end diff --git a/actionview/lib/action_view/helpers/text_helper.rb b/actionview/lib/action_view/helpers/text_helper.rb index 8203a43239..980a89a7b6 100644 --- a/actionview/lib/action_view/helpers/text_helper.rb +++ b/actionview/lib/action_view/helpers/text_helper.rb @@ -228,7 +228,7 @@ module ActionView # pluralize(2, 'Person', locale: :de) # # => 2 Personen def pluralize(count, singular, plural_arg = nil, plural: plural_arg, locale: I18n.locale) - word = if count == 1 || count.to_s =~ /^1(\.0+)?$/ + word = if count == 1 || count.to_s.match?(/^1(\.0+)?$/) singular else plural || singular.pluralize(locale) diff --git a/actionview/lib/action_view/helpers/url_helper.rb b/actionview/lib/action_view/helpers/url_helper.rb index 4b3a258287..61ab3c2e13 100644 --- a/actionview/lib/action_view/helpers/url_helper.rb +++ b/actionview/lib/action_view/helpers/url_helper.rb @@ -45,7 +45,7 @@ module ActionView def _back_url # :nodoc: _filtered_referrer || "javascript:history.back()" end - protected :_back_url + private :_back_url def _filtered_referrer # :nodoc: if controller.respond_to?(:request) @@ -56,12 +56,12 @@ module ActionView end rescue URI::InvalidURIError end - protected :_filtered_referrer + private :_filtered_referrer # Creates an anchor element of the given +name+ using a URL created by the set of +options+. # See the valid options in the documentation for +url_for+. It's also possible to - # pass a String instead of an options hash, which generates an anchor element that uses the - # value of the String as the href for the link. Using a <tt>:back</tt> Symbol instead + # pass a \String instead of an options hash, which generates an anchor element that uses the + # value of the \String as the href for the link. Using a <tt>:back</tt> \Symbol instead # of an options hash will generate a link to the referrer (a JavaScript back link # will be used in place of a referrer if none exists). If +nil+ is passed as the name # the value of the link itself will become the name. @@ -226,7 +226,7 @@ module ActionView # The +options+ hash accepts the same options as +url_for+. # # There are a few special +html_options+: - # * <tt>:method</tt> - Symbol of HTTP verb. Supported verbs are <tt>:post</tt>, <tt>:get</tt>, + # * <tt>:method</tt> - \Symbol of HTTP verb. Supported verbs are <tt>:post</tt>, <tt>:get</tt>, # <tt>:delete</tt>, <tt>:patch</tt>, and <tt>:put</tt>. By default it will be <tt>:post</tt>. # * <tt>:disabled</tt> - If set to true, it will generate a disabled button. # * <tt>:data</tt> - This option can be used to add custom data attributes. @@ -235,7 +235,7 @@ module ActionView # * <tt>:form</tt> - This hash will be form attributes # * <tt>:form_class</tt> - This controls the class of the form within which the submit button will # be placed - # * <tt>:params</tt> - Hash of parameters to be rendered as hidden fields within the form. + # * <tt>:params</tt> - \Hash of parameters to be rendered as hidden fields within the form. # # ==== Data attributes # @@ -571,6 +571,101 @@ module ActionView end end + # Creates an SMS anchor link tag to the specified +phone_number+, which is + # also used as the name of the link unless +name+ is specified. Additional + # HTML attributes for the link can be passed in +html_options+. + # + # When clicked, an SMS message is prepopulated with the passed phone number + # and optional +body+ value. + # + # +sms_to+ has a +body+ option for customizing the SMS message itself by + # passing special keys to +html_options+. + # + # ==== Options + # * <tt>:body</tt> - Preset the body of the message. + # + # ==== Examples + # sms_to "5155555785" + # # => <a href="sms:5155555785;">5155555785</a> + # + # sms_to "5155555785", "Text me" + # # => <a href="sms:5155555785;">Text me</a> + # + # sms_to "5155555785", "Text me", + # body: "Hello Jim I have a question about your product." + # # => <a href="sms:5155555785;?body=Hello%20Jim%20I%20have%20a%20question%20about%20your%20product">Text me</a> + # + # You can use a block as well if your link target is hard to fit into the name parameter. \ERB example: + # + # <%= sms_to "5155555785" do %> + # <strong>Text me:</strong> + # <% end %> + # # => <a href="sms:5155555785;"> + # <strong>Text me:</strong> + # </a> + def sms_to(phone_number, name = nil, html_options = {}, &block) + html_options, name = name, nil if block_given? + html_options = (html_options || {}).stringify_keys + + extras = %w{ body }.map! { |item| + option = html_options.delete(item).presence || next + "#{item.dasherize}=#{ERB::Util.url_encode(option)}" + }.compact + extras = extras.empty? ? "" : "?&" + extras.join("&") + + encoded_phone_number = ERB::Util.url_encode(phone_number) + html_options["href"] = "sms:#{encoded_phone_number};#{extras}" + + content_tag("a", name || phone_number, html_options, &block) + end + + # Creates a TEL anchor link tag to the specified +phone_number+, which is + # also used as the name of the link unless +name+ is specified. Additional + # HTML attributes for the link can be passed in +html_options+. + # + # When clicked, the default app to make calls is opened, and it + # is prepopulated with the passed phone number and optional + # +country_code+ value. + # + # +phone_to+ has an optional +country_code+ option which automatically adds the country + # code as well as the + sign in the phone numer that gets prepopulated, + # for example if +country_code: "01"+ +\+01+ will be prepended to the + # phone numer, by passing special keys to +html_options+. + # + # ==== Options + # * <tt>:country_code</tt> - Prepends the country code to the number + # + # ==== Examples + # phone_to "1234567890" + # # => <a href="tel:1234567890">1234567890</a> + # + # phone_to "1234567890", "Phone me" + # # => <a href="tel:134567890">Phone me</a> + # + # phone_to "1234567890", "Phone me", country_code: "01" + # # => <a href="tel:+015155555785">Phone me</a> + # + # You can use a block as well if your link target is hard to fit into the name parameter. \ERB example: + # + # <%= phone_to "1234567890" do %> + # <strong>Phone me:</strong> + # <% end %> + # # => <a href="tel:1234567890"> + # <strong>Phone me:</strong> + # </a> + def phone_to(phone_number, name = nil, html_options = {}, &block) + html_options, name = name, nil if block_given? + html_options = (html_options || {}).stringify_keys + + country_code = html_options.delete("country_code").presence + country_code = country_code.nil? ? "" : "+#{ERB::Util.url_encode(country_code)}" + + encoded_phone_number = ERB::Util.url_encode(phone_number) + html_options["href"] = "tel:#{country_code}#{encoded_phone_number}" + + content_tag("a", name || phone_number, html_options, &block) + end + private def convert_options_to_data_attributes(options, html_options) if html_options @@ -594,7 +689,7 @@ module ActionView end def add_method_to_attributes!(html_options, method) - if method_not_get_method?(method) && html_options["rel"] !~ /nofollow/ + if method_not_get_method?(method) && !html_options["rel"]&.match?(/nofollow/) if html_options["rel"].blank? html_options["rel"] = "nofollow" else diff --git a/actionview/lib/action_view/layouts.rb b/actionview/lib/action_view/layouts.rb index be21ff0e5d..b21dc1b9b3 100644 --- a/actionview/lib/action_view/layouts.rb +++ b/actionview/lib/action_view/layouts.rb @@ -306,7 +306,7 @@ module ActionView RUBY when Proc define_method :_layout_from_proc, &_layout - protected :_layout_from_proc + private :_layout_from_proc <<-RUBY result = _layout_from_proc(#{_layout.arity == 0 ? '' : 'self'}) return #{default_behavior} if result.nil? @@ -395,7 +395,7 @@ module ActionView end def _normalize_layout(value) - value.is_a?(String) && value !~ /\blayouts/ ? "layouts/#{value}" : value + value.is_a?(String) && !value.match?(/\blayouts/) ? "layouts/#{value}" : value end # Returns the default layout for this controller. diff --git a/actionview/lib/action_view/lookup_context.rb b/actionview/lib/action_view/lookup_context.rb index 138ffa515b..f050d54e27 100644 --- a/actionview/lib/action_view/lookup_context.rb +++ b/actionview/lib/action_view/lookup_context.rb @@ -3,7 +3,6 @@ require "concurrent/map" require "active_support/core_ext/module/remove_method" require "active_support/core_ext/module/attribute_accessors" -require "active_support/deprecation" require "action_view/template/resolver" module ActionView @@ -30,7 +29,7 @@ module ActionView Accessors.define_method(:"default_#{name}", &block) Accessors.module_eval <<-METHOD, __FILE__, __LINE__ + 1 def #{name} - @details.fetch(:#{name}, []) + @details[:#{name}] || [] end def #{name}=(value) diff --git a/actionview/lib/action_view/renderer/streaming_template_renderer.rb b/actionview/lib/action_view/renderer/streaming_template_renderer.rb index 08a280c7ee..5942717b8d 100644 --- a/actionview/lib/action_view/renderer/streaming_template_renderer.rb +++ b/actionview/lib/action_view/renderer/streaming_template_renderer.rb @@ -62,7 +62,7 @@ module ActionView output = ActionView::StreamingBuffer.new(buffer) yielder = lambda { |*name| view._layout_for(*name) } - instrument(:template, identifier: template.identifier, layout: layout.try(:virtual_path)) do + instrument(:template, identifier: template.identifier, layout: (layout && layout.virtual_path)) do outer_config = I18n.config fiber = Fiber.new do I18n.config = outer_config diff --git a/actionview/lib/action_view/renderer/template_renderer.rb b/actionview/lib/action_view/renderer/template_renderer.rb index b2d7332572..da0b2dc0d2 100644 --- a/actionview/lib/action_view/renderer/template_renderer.rb +++ b/actionview/lib/action_view/renderer/template_renderer.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true -require "active_support/core_ext/object/try" - module ActionView class TemplateRenderer < AbstractRenderer #:nodoc: def render(context, options) @@ -54,7 +52,7 @@ module ActionView # supplied as well. def render_template(view, template, layout_name, locals) render_with_layout(view, template, layout_name, locals) do |layout| - instrument(:template, identifier: template.identifier, layout: layout.try(:virtual_path)) do + instrument(:template, identifier: template.identifier, layout: (layout && layout.virtual_path)) do template.render(view, locals) { |*name| view._layout_for(*name) } end end diff --git a/actionview/lib/action_view/template.rb b/actionview/lib/action_view/template.rb index 88320dcd0d..3877108fef 100644 --- a/actionview/lib/action_view/template.rb +++ b/actionview/lib/action_view/template.rb @@ -1,8 +1,6 @@ # frozen_string_literal: true -require "active_support/core_ext/object/try" require "active_support/core_ext/kernel/singleton_class" -require "active_support/deprecation" require "thread" require "delegate" diff --git a/actionview/lib/action_view/template/error.rb b/actionview/lib/action_view/template/error.rb index feceef15f9..7fc74a5502 100644 --- a/actionview/lib/action_view/template/error.rb +++ b/actionview/lib/action_view/template/error.rb @@ -81,8 +81,8 @@ module ActionView end end - def source_extract(indentation = 0, output = :console) - return unless num = line_number + def source_extract(indentation = 0) + return [] unless num = line_number num = num.to_i source_code = @template.source.split("\n") @@ -91,9 +91,9 @@ module ActionView end_on_line = [ num + SOURCE_CODE_RADIUS - 1, source_code.length].min indent = end_on_line.to_s.size + indentation - return unless source_code = source_code[start_on_line..end_on_line] + return [] unless source_code = source_code[start_on_line..end_on_line] - formatted_code_for(source_code, start_on_line, indent, output) + formatted_code_for(source_code, start_on_line, indent) end def sub_template_of(template_path) @@ -122,15 +122,11 @@ module ActionView end + file_name end - def formatted_code_for(source_code, line_counter, indent, output) - start_value = (output == :html) ? {} : [] - source_code.inject(start_value) do |result, line| + def formatted_code_for(source_code, line_counter, indent) + indent_template = "%#{indent}s: %s" + source_code.map do |line| line_counter += 1 - if output == :html - result.update(line_counter.to_s => "%#{indent}s %s\n" % ["", line]) - else - result << "%#{indent}s: %s" % [line_counter, line] - end + indent_template % [line_counter, line] end end end diff --git a/actionview/lib/action_view/template/handlers.rb b/actionview/lib/action_view/template/handlers.rb index 6450513003..c7ef456125 100644 --- a/actionview/lib/action_view/template/handlers.rb +++ b/actionview/lib/action_view/template/handlers.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true -require "active_support/deprecation" - module ActionView #:nodoc: # = Action View Template Handlers class Template #:nodoc: diff --git a/actionview/lib/action_view/template/html.rb b/actionview/lib/action_view/template/html.rb index ecd1c31e79..563bffd333 100644 --- a/actionview/lib/action_view/template/html.rb +++ b/actionview/lib/action_view/template/html.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true -require "active_support/deprecation" - module ActionView #:nodoc: # = Action View HTML Template class Template #:nodoc: diff --git a/actionview/lib/action_view/testing/resolvers.rb b/actionview/lib/action_view/testing/resolvers.rb index 539bedcdf0..03eac29bb4 100644 --- a/actionview/lib/action_view/testing/resolvers.rb +++ b/actionview/lib/action_view/testing/resolvers.rb @@ -7,10 +7,15 @@ module ActionView #:nodoc: # file system. This is used internally by Rails' own test suite, and is # useful for testing extensions that have no way of knowing what the file # system will look like at runtime. - class FixtureResolver < PathResolver + class FixtureResolver < OptimizedFileSystemResolver def initialize(hash = {}, pattern = nil) - super(pattern) + super("") + if pattern + ActiveSupport::Deprecation.warn "Specifying a custom path for #{self.class} is deprecated. Implement a custom Resolver subclass instead." + @pattern = pattern + end @hash = hash + @path = "" end def data @@ -23,25 +28,32 @@ module ActionView #:nodoc: private def query(path, exts, _, locals, cache:) - query = +"" - EXTENSIONS.each do |ext, prefix| - query << "(" << exts[ext].map { |e| e && Regexp.escape("#{prefix}#{e}") }.join("|") << "|)" - end - query = /^(#{Regexp.escape(path)})#{query}$/ + regex = build_regex(path, exts) - templates = [] - @hash.each do |_path, source| - next unless query.match?(_path) + @hash.select do |_path, _| + ("/" + _path).match?(regex) + end.map do |_path, source| handler, format, variant = extract_handler_and_format_and_variant(_path) - templates << Template.new(source, _path, handler, + + Template.new(source, _path, handler, virtual_path: path.virtual, format: format, variant: variant, locals: locals ) + end.sort_by do |t| + match = ("/" + t.identifier).match(regex) + EXTENSIONS.keys.reverse.map do |ext| + if ext == :variants && exts[ext] == :any + match[ext].nil? ? 0 : 1 + elsif match[ext].nil? + exts[ext].length + else + found = match[ext].to_sym + exts[ext].index(found) + end + end end - - templates.sort_by { |t| -t.identifier.match(/^#{query}$/).captures.reject(&:blank?).size } end end diff --git a/actionview/lib/action_view/unbound_template.rb b/actionview/lib/action_view/unbound_template.rb index d28bab91b6..3d4434b2e9 100644 --- a/actionview/lib/action_view/unbound_template.rb +++ b/actionview/lib/action_view/unbound_template.rb @@ -4,9 +4,9 @@ require "concurrent/map" module ActionView class UnboundTemplate - def initialize(source, identifer, handler, options) + def initialize(source, identifier, handler, options) @source = source - @identifer = identifer + @identifier = identifier @handler = handler @options = options @@ -22,7 +22,7 @@ module ActionView options = @options.merge(locals: locals) Template.new( @source, - @identifer, + @identifier, @handler, options ) |