Merge pull request #45957 from jhawthorn/immutable_path_set

Make ActionView::PathSet immutable
This commit is contained in:
John Hawthorn 2022-09-07 11:40:53 -07:00 committed by GitHub
commit f5d676cd97
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 24 additions and 18 deletions

View File

@ -148,11 +148,23 @@ module ActionView
end end
alias :any_templates? :any? alias :any_templates? :any?
def append_view_paths(paths)
@view_paths = build_view_paths(@view_paths.to_a + paths)
end
def prepend_view_paths(paths)
@view_paths = build_view_paths(paths + @view_paths.to_a)
end
private private
# Whenever setting view paths, makes a copy so that we can manipulate them in # Whenever setting view paths, makes a copy so that we can manipulate them in
# instance objects as we wish. # instance objects as we wish.
def build_view_paths(paths) def build_view_paths(paths)
ActionView::PathSet.new(Array(paths)) if ActionView::PathSet === paths
paths
else
ActionView::PathSet.new(Array(paths))
end
end end
# Compute details hash and key according to user options (e.g. passed from #render). # Compute details hash and key according to user options (e.g. passed from #render).

View File

@ -13,14 +13,14 @@ module ActionView # :nodoc:
attr_reader :paths attr_reader :paths
delegate :[], :include?, :pop, :size, :each, to: :paths delegate :[], :include?, :size, :each, to: :paths
def initialize(paths = []) def initialize(paths = [])
@paths = typecast paths @paths = typecast(paths).freeze
end end
def initialize_copy(other) def initialize_copy(other)
@paths = other.paths.dup @paths = other.paths.dup.freeze
self self
end end
@ -36,14 +36,6 @@ module ActionView # :nodoc:
PathSet.new(paths + array) PathSet.new(paths + array)
end end
%w(<< concat push insert unshift).each do |method|
class_eval <<-METHOD, __FILE__, __LINE__ + 1
def #{method}(*args)
paths.#{method}(*typecast(args))
end
METHOD
end
def find(path, prefixes, partial, details, details_key, locals) def find(path, prefixes, partial, details, details_key, locals)
find_all(path, prefixes, partial, details, details_key, locals).first || find_all(path, prefixes, partial, details, details_key, locals).first ||
raise(MissingTemplate.new(self, path, prefixes, partial, details, details_key, locals)) raise(MissingTemplate.new(self, path, prefixes, partial, details, details_key, locals))
@ -76,8 +68,10 @@ module ActionView # :nodoc:
case path case path
when Pathname, String when Pathname, String
FileSystemResolver.new path.to_s FileSystemResolver.new path.to_s
else when Resolver
path path
else
raise TypeError, "#{path.inspect} is not a valid path: must be a String, Pathname, or Resolver"
end end
end end
end end

View File

@ -35,7 +35,7 @@ module ActionView
# the default view path. You may also provide a custom view path # the default view path. You may also provide a custom view path
# (see ActionView::PathSet for more information) # (see ActionView::PathSet for more information)
def append_view_path(path) def append_view_path(path)
self._view_paths = view_paths + Array(path) self._view_paths = ActionView::PathSet.new(view_paths.to_a + Array(path))
end end
# Prepend a path to the list of view paths for this controller. # Prepend a path to the list of view paths for this controller.
@ -45,7 +45,7 @@ module ActionView
# the default view path. You may also provide a custom view path # the default view path. You may also provide a custom view path
# (see ActionView::PathSet for more information) # (see ActionView::PathSet for more information)
def prepend_view_path(path) def prepend_view_path(path)
self._view_paths = ActionView::PathSet.new(Array(path) + view_paths) self._view_paths = ActionView::PathSet.new(Array(path) + view_paths.to_a)
end end
# A list of all of the default view paths for this controller. # A list of all of the default view paths for this controller.
@ -110,7 +110,7 @@ module ActionView
# the default view path. You may also provide a custom view path # the default view path. You may also provide a custom view path
# (see ActionView::PathSet for more information) # (see ActionView::PathSet for more information)
def append_view_path(path) def append_view_path(path)
lookup_context.view_paths.push(*path) lookup_context.append_view_paths(Array(path))
end end
# Prepend a path to the list of view paths for the current LookupContext. # Prepend a path to the list of view paths for the current LookupContext.
@ -120,7 +120,7 @@ module ActionView
# the default view path. You may also provide a custom view path # the default view path. You may also provide a custom view path
# (see ActionView::PathSet for more information) # (see ActionView::PathSet for more information)
def prepend_view_path(path) def prepend_view_path(path)
lookup_context.view_paths.unshift(*path) lookup_context.prepend_view_paths(Array(path))
end end
end end
end end

View File

@ -155,7 +155,7 @@ class ViewLoadPathsTest < ActionController::TestCase
end end
decorator = decorator_class.new(TestController.view_paths) decorator = decorator_class.new(TestController.view_paths)
TestController.view_paths = ActionView::PathSet.new.push(decorator) TestController.view_paths = ActionView::PathSet.new([decorator])
get :hello_world get :hello_world
assert_response :success assert_response :success