Skip to content

Commit

Permalink
Merge pull request #35074 from rails/ro-lookup-context
Browse files Browse the repository at this point in the history
Make the lookup context more "read-only"
  • Loading branch information
tenderlove committed Jan 28, 2019
2 parents c0154b5 + 0b0412a commit 8f8d8b3
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 25 deletions.
24 changes: 10 additions & 14 deletions actionview/lib/action_view/lookup_context.rb
Expand Up @@ -106,12 +106,6 @@ def _set_detail(key, value) # :doc:
module ViewPaths
attr_reader :view_paths, :html_fallback_for_js

# Whenever setting view paths, makes a copy so that we can manipulate them in
# instance objects as we wish.
def view_paths=(paths)
@view_paths = ActionView::PathSet.new(Array(paths))
end

def find(name, prefixes = [], partial = false, keys = [], options = {})
@view_paths.find(*args_for_lookup(name, prefixes, partial, keys, options))
end
Expand All @@ -138,19 +132,21 @@ def any?(name, prefixes = [], partial = false)
# Adds fallbacks to the view paths. Useful in cases when you are rendering
# a :file.
def with_fallbacks
added_resolvers = 0
self.class.fallbacks.each do |resolver|
next if view_paths.include?(resolver)
view_paths.push(resolver)
added_resolvers += 1
end
view_paths = @view_paths
@view_paths = build_view_paths((view_paths.paths + self.class.fallbacks).uniq)
yield
ensure
added_resolvers.times { view_paths.pop }
@view_paths = view_paths
end

private

# Whenever setting view paths, makes a copy so that we can manipulate them in
# instance objects as we wish.
def build_view_paths(paths)
ActionView::PathSet.new(Array(paths))
end

def args_for_lookup(name, prefixes, partial, keys, details_options)
name, prefixes = normalize_name(name, prefixes)
details, details_key = detail_args_for(details_options)
Expand Down Expand Up @@ -226,7 +222,7 @@ def initialize(view_paths, details = {}, prefixes = [])
@rendered_format = nil

@details = initialize_details({}, details)
self.view_paths = view_paths
@view_paths = build_view_paths(view_paths)
end

def digest_cache
Expand Down
6 changes: 4 additions & 2 deletions actionview/lib/action_view/testing/resolvers.rb
Expand Up @@ -8,13 +8,15 @@ module ActionView #:nodoc:
# useful for testing extensions that have no way of knowing what the file
# system will look like at runtime.
class FixtureResolver < PathResolver
attr_reader :hash

def initialize(hash = {}, pattern = nil)
super(pattern)
@hash = hash
end

def data
@hash
end

def to_s
@hash.keys.join(", ")
end
Expand Down
22 changes: 13 additions & 9 deletions actionview/test/template/lookup_context_test.rb
Expand Up @@ -5,10 +5,14 @@

class LookupContextTest < ActiveSupport::TestCase
def setup
@lookup_context = ActionView::LookupContext.new(FIXTURE_LOAD_PATH, {})
@lookup_context = build_lookup_context(FIXTURE_LOAD_PATH, {})
ActionView::LookupContext::DetailsKey.clear
end

def build_lookup_context(paths, details)
ActionView::LookupContext.new(paths, details)
end

def teardown
I18n.locale = :en
end
Expand Down Expand Up @@ -156,13 +160,13 @@ def teardown
end

test "gives the key forward to the resolver, so it can be used as cache key" do
@lookup_context.view_paths = ActionView::FixtureResolver.new("test/_foo.erb" => "Foo")
@lookup_context = build_lookup_context(ActionView::FixtureResolver.new("test/_foo.erb" => "Foo"), {})
template = @lookup_context.find("foo", %w(test), true)
assert_equal "Foo", template.source

# Now we are going to change the template, but it won't change the returned template
# since we will hit the cache.
@lookup_context.view_paths.first.hash["test/_foo.erb"] = "Bar"
@lookup_context.view_paths.first.data["test/_foo.erb"] = "Bar"
template = @lookup_context.find("foo", %w(test), true)
assert_equal "Foo", template.source

Expand All @@ -185,7 +189,7 @@ def teardown
end

test "can disable the cache on demand" do
@lookup_context.view_paths = ActionView::FixtureResolver.new("test/_foo.erb" => "Foo")
@lookup_context = build_lookup_context(ActionView::FixtureResolver.new("test/_foo.erb" => "Foo"), {})
old_template = @lookup_context.find("foo", %w(test), true)

template = @lookup_context.find("foo", %w(test), true)
Expand Down Expand Up @@ -221,12 +225,12 @@ def setup

# Now we are going to change the template, but it won't change the returned template
# since the timestamp is the same.
@resolver.hash["test/_foo.erb"][0] = "Bar"
@resolver.data["test/_foo.erb"][0] = "Bar"
template = @lookup_context.find("foo", %w(test), true)
assert_equal "Foo", template.source

# Now update the timestamp.
@resolver.hash["test/_foo.erb"][1] = Time.now.utc
@resolver.data["test/_foo.erb"][1] = Time.now.utc
template = @lookup_context.find("foo", %w(test), true)
assert_equal "Bar", template.source
end
Expand All @@ -237,7 +241,7 @@ def setup
template = @lookup_context.find("foo", %w(test), true)
assert_equal "Foo", template.source

@resolver.hash.clear
@resolver.data.clear
assert_raise ActionView::MissingTemplate do
@lookup_context.find("foo", %w(test), true)
end
Expand All @@ -246,12 +250,12 @@ def setup

test "if no template was cached in the first lookup, retrieval should work in the second call" do
ActionView::Resolver.stub(:caching?, false) do
@resolver.hash.clear
@resolver.data.clear
assert_raise ActionView::MissingTemplate do
@lookup_context.find("foo", %w(test), true)
end

@resolver.hash["test/_foo.erb"] = ["Foo", Time.utc(2000)]
@resolver.data["test/_foo.erb"] = ["Foo", Time.utc(2000)]
template = @lookup_context.find("foo", %w(test), true)
assert_equal "Foo", template.source
end
Expand Down

0 comments on commit 8f8d8b3

Please sign in to comment.