When dealing with the "details" for a template: locale, format,
variant, and handler, previously we would store these in an ad-hoc way
every place we did. Often as a hash or as separate instance variables on
a class.
This PR attempts to simplify this by encapsulating known details on a
template in a new ActionView::TemplateDetails class, and requested
details in ActionView::TemplateDetails::Requested.
This allowed extracting and simplifying filtering and sorting logic from
the Resolver class as well as extracting default format logic from
UnboundTemplate.
As well as reducing complexity, in the future this should make it
possible to provide suggestions on missing template errors due to
mismatched details, and might allow improved performance.
At least for now these new classes are private (:nodoc)
Co-authored-by: John Crepezzi <john.crepezzi@gmail.com>
This is called on every render or template lookup.
lookup_context = ActionController::Base.new.lookup_context
normalize = lookup_context.method(:normalize_name)
Benchmark.ips do |x|
x.report "already normalized" do
normalize.call("show", ["users"])
end
x.report "without prefixes" do
normalize.call("users/show", [])
end
x.report "with prefixes in both arguments" do
normalize.call("extra/show", ["users", "application"])
end
end
Before:
already normalized 2.322M (± 0.5%) i/s - 11.615M in 5.003512s
without prefixes 1.613M (± 0.7%) i/s - 8.076M in 5.007165s
with prefixes in both arguments
1.020M (± 0.7%) i/s - 5.154M in 5.054101s
After:
already normalized 3.740M (± 0.3%) i/s - 18.715M in 5.003477s
without prefixes 2.197M (± 0.6%) i/s - 11.089M in 5.047800s
with prefixes in both arguments
1.244M (± 0.9%) i/s - 6.246M in 5.020968s
url_for supports building polymorphic URLs via an array
of arguments (usually symbols and records). If an array is passed,
strings can result in unwanted route helper calls.
CVE-2021-22885
`codespell` works with a small custom dictionary and seems to find perhaps more spelling mistakes than `misspell` which really only fixes commonly misspelled English words.
Not all spell checkers can check all file types and most spell checkers can't find all the errors.
https://github.com/codespell-project/codespellhttps://pypi.org/project/codespell/
A default value can be a string that needs interpolation, Hash that
needs resolution via the `:count` option, or a Proc that needs
evaluation. Therefore, pass default values through `I18n.translate` to
handle these cases.
Fixes#26032.
Fixes#41277.
Fixes#41380.
In old versions of Rails, we would rely entirely on what was returned by
Dir.glob to determine the match and sorting of our templates.
Later we switched to building a regex on each search, which allowed us
to perform a much faster glob, find matching templates with the regex,
and then emulate the sort order based on captures from the regex.
Now we have PathParser, which can parse any template's details
accurately from just its filename (not depending on the query being
made).
This commit moves the matching to done on UnboundTemplates, effectively
using details found by the PathParser for both matching and sorting of
templates, and removing the dynamic regex for queries.
This should be faster at boot/after reloads as we're no longer building
a regex and additionally we only need to parse a template's path for
details one time (we can use the same details for matching/sorting in
future queries with different details).
Previously, it was possible for these not to match due to providing
templates with .'s or using fallback templates.
There is now an exact 1:1 between templates on disk and virtual path.
Previously we just stored handler, format, and variant and assigned a
default format if none existed.
Now we want to also store locale, and move the default format behaviour
into unbound template.
Previously we would check that our paths were safe and inside the app
right before building templates. Instead we can do this, and reject
directories at the same time as we perform the glob.
Co-authored-by: Kasper Timm Hansen <kaspth@gmail.com>
Before this change did_you_mean shows partial paths like `animals/_partial`,
but adding that to your render call in a view like `<%= render 'animals/_partial' %>`
will still be missing as rails will search for the template `animals/__partial`.
We can provide the user a easier copy/paste correction if we don't tell them about the underscore.
This also reduces the candidates to only return partials if you are
looking for a partial and only look for non-templates when you are not
looking for a template.
This updates ActionView::CacheExpiry to hold a lock while inside the
executor (ie. inside a request) and to only clear caches when that is
done.
This is done using Concurrent::ReadWriteLock. This allows any number
of parallel requests to hold the read lock, but once we detect a change
and begin to acquire the write lock, all future requests will be
blocked.