| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
| |
|
|
|
|
|
| |
Now that Template#source will always return a source, this is
unnecessary.
|
|
|
|
|
|
|
|
|
|
| |
Previously, we would discard the template source after rendering, if we
had a virtual path, in hopes that the virtual path would let us find our
same template again going through the Resolver.
Previously we discarded the source as an optimization, to avoid keeping
it around in memory. By instead just reading the file every time source
is called, as FileTemplate does, this is unnecessary.
|
| |
|
|\
| |
| | |
RFC: Introduce Template::File
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
The previous behaviour of render file: was essentially the same as
render template:, except that templates can be specified as an absolute
path on the filesystem.
This makes sense for historic reasons, but now render file: is almost
exclusively used to render raw files (not .erb) like public/404.html. In
addition to complicating the code in template/resolver.rb, I think the
current behaviour is surprising to developers.
This commit deprecates the existing "lookup a template from anywhere"
behaviour and replaces it with "render this file exactly as it is on
disk". Handlers will no longer be used (it will render the same as if
the :raw handler was used), but formats (.html, .xml, etc) will still be
detected (and will default to :plain).
The existing render file: behaviour was the path through which Rails
apps were vulnerable in the recent CVE-2019-5418. Although the
vulnerability has been patched in a fully backwards-compatible way, I
think it's a strong hint that we should drop the existing
previously-vulnerable behaviour if it isn't a benefit to developers.
|
|\ \
| |/
|/|
| |
| | |
erose/better-error-reporting-for-syntax-errors-in-templates
Display a more helpful error message when an ERB template has a Ruby syntax error.
|
| | |
|
| | |
|
|\ \
| | |
| | | |
Make Template::Resolver always cache
|
| | | |
|
|/ /
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
There was a recent change by @tenderlove to Action view which introduced
`ActionView::Base#run` [1].
We ran into an issue with our application because one of the core
concepts in our domain model is a `Run` which is exposed in most of our
views as a helper method, which now conflicts with this new method.
Although this is a public method it is not really meant to be part of
the public API.
In order to discourage public use of this method and to reduce the
chances of this method conflicting with helper methods we can prefix
this method with an underscore, renaming this method to `_run`.
[1] https://github.com/rails/rails/commit/c740ebdaf5
|
| | |
|
| | |
|
| | |
|
| |
| |
| |
| |
| |
| | |
`virtual_path` is calculated in the constructor when the Template object
is allocated. We don't actually need to set it in the `decorate`
method. That means we can remove the decorate method all together.
|
| |
| |
| |
| |
| |
| |
| | |
This commit ensures that locals are passed in to the template objects
when they are constructed, then removes the `locals=` mutator on the
template object. This means we don't need to mutate Template objects
with locals in the `decorate` method.
|
|\ \
| | |
| | | |
Template has one variant
|
| | |
| | |
| | |
| | |
| | |
| | | |
Templates only have one variant, so we should not store it in an array.
This commit converts `variants` to `variant` and deprecates the plural
accessor
|
| | | |
|
|/ /
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
* Don't call inspect from identifier_method_name
* Add locals Template#inspect
Handler, formats, and variant are usually obvious from looking at the
identifier. However it's not uncommon to have different locals for the
same template so we should make that obvious in inspect.
* Add tests for short_identifier and inspect
[John Hawthorn + Rafael Mendonça França]
|
| |
| |
| |
| |
| |
| |
| | |
Templates only have one format. Before this commit, templates would be
constructed with a single element array that contained the format. This
commit eliminates the single element array and just implements a
`format` method. This saves one array allocation per template.
|
| |
| |
| | |
Co-Authored-By: tenderlove <tenderlove@github.com>
|
| | |
|
| |
| |
| |
| |
| | |
The format should always be exactly one symbol. Now we don't need to
check whether or not the format is a `Type` in the constructor.
|
| |
| |
| |
| |
| | |
This means we can eliminate nil checks and remove some mutations from
the `decorate` method.
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
This commit adds a finalizer just to inline templates. We can't cache
compilation of inline templates because it's possible that people could
have render calls that look like this:
```ruby
loop do
render inline: "#{rand}"
end
```
and we would cache every one of these different inline templates. That
would cause a memory leak. OTOH, we don't need finalizers on regular
templates because we can cache, control, and detect changes to the
template source.
Fixes: #35372
|
|/
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This commit passes the template format to the digestor in order to come
up with a key. Before this commit, the digestor would depend on the
side effect of the template renderer setting the rendered_format on the
lookup context. I would like to remove that mutation, so I've changed
this to pass the template format in to the digestor.
I've introduced a new instance variable that will be alive during a
template render. When the template is being rendered, it pushes the
current template on to a stack, setting `@current_template` to the
template currently being rendered. When the cache helper asks the
digestor for a key, it uses the format of the template currently on the
stack.
|
|
|
|
|
|
| |
Revert "Remove finalizer and configuration"
This reverts commit 9e7b4a3173788ea43b11e74a4d2f69a5f1565daa.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This commit speeds up rendering partials by caching the variable name
calculation on the template. The variable name is based on the "virtual
path" used for looking up the template. The same virtual path
information lives on the template, so we can just ask the cached
template object for the variable.
This benchmark takes a couple files, so I'll cat them below:
```
[aaron@TC ~/g/r/actionview (speed-up-partials)]$ cat render_benchmark.rb
require "benchmark/ips"
require "action_view"
require "action_pack"
require "action_controller"
class TestController < ActionController::Base
end
TestController.view_paths = [File.expand_path("test/benchmarks")]
controller_view = TestController.new.view_context
result = Benchmark.ips do |x|
x.report("render") do
controller_view.render("many_partials")
end
end
[aaron@TC ~/g/r/actionview (speed-up-partials)]$ cat test/benchmarks/test/_many_partials.html.erb
Looping:
<ul>
<% 100.times do |i| %>
<%= render partial: "list_item", locals: { i: i } %>
<% end %>
</ul>
[aaron@TC ~/g/r/actionview (speed-up-partials)]$ cat test/benchmarks/test/_list_item.html.erb
<li>Number: <%= i %></li>
```
Benchmark results (master):
```
[aaron@TC ~/g/r/actionview (master)]$ be ruby render_benchmark.rb
Warming up --------------------------------------
render 41.000 i/100ms
Calculating -------------------------------------
render 424.269 (± 3.5%) i/s - 2.132k in 5.031455s
```
Benchmark results (this branch):
```
[aaron@TC ~/g/r/actionview (speed-up-partials)]$ be ruby render_benchmark.rb
Warming up --------------------------------------
render 50.000 i/100ms
Calculating -------------------------------------
render 521.862 (± 3.8%) i/s - 2.650k in 5.085885s
```
|
|
|
|
|
|
|
|
|
| |
This commit passes the mutated source to the template handler as a
parameter and deprecates the old handlers. Old handlers required that
templates contain a reference to mutated source code, but we would like
to make template objects "read only". This change lets the template
remain "read only" while still giving template handlers access to the
source code after mutations.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Every template that specifies a "virtual path" loses the template source
when the template gets compiled:
https://github.com/rails/rails/blob/eda0f574f129fcd5ad1fc58b55cb6d1db71ea95c/actionview/lib/action_view/template.rb#L275
The "refresh" method seems to think that the source code for a template
can be recovered if there is a virtual path:
https://github.com/rails/rails/blob/eda0f574f129fcd5ad1fc58b55cb6d1db71ea95c/actionview/lib/action_view/template.rb#L171-L188
Every call site that allocates a template object *and* provides a
"virtual path" reads the template contents from the filesystem:
https://github.com/rails/rails/blob/eda0f574f129fcd5ad1fc58b55cb6d1db71ea95c/actionview/lib/action_view/template/resolver.rb#L229-L231
Templates that are inline or literals don't provide a "virtual path":
https://github.com/rails/rails/blob/eda0f574f129fcd5ad1fc58b55cb6d1db71ea95c/actionview/lib/action_view/renderer/template_renderer.rb#L34
This commit introduces a `FileTemplate` type that subclasses `Template`.
The `FileTemplate` keeps a reference to the filename, and reads the
source from the filesystem. This effectively makes the template source
immutable.
Other classes depended on the source to be mutated while being compiled,
so this commit also introduces a temporary way to pass the mutated
source to the ERB (or whatever) compiler. See `LegacyTemplate`.
I think we should consider it an error to provide a virtual path on a
non file type template an non-file templates can't recover their source.
Here is an example:
https://github.com/rails/rails/blob/eda0f574f129fcd5ad1fc58b55cb6d1db71ea95c/actionview/lib/action_view/testing/resolvers.rb#L53
This provides a "virtual path" so the source code (a string literal) is
thrown away after compilation. Clearly we can't recover that string, so
I think this should be an error.
|
| |
|
|
|
|
|
|
| |
Rather than doing is_a? checks, ask the view object for its compiled
method container. This gives us the power to replace the method
container depending on the instance of the view.
|
| |
|
|
|
|
|
| |
Methods created by views should always be evaluated against an AV::Base
instance. This way we can extract and refactor things in to classes.
|
|
|
|
|
|
| |
This pulls the "output buffer existence" conditional up. Instead of
evaling the same conditional over and over, we can pull it in to "only
compiled once" Ruby code.
|
|
|
|
|
|
|
|
| |
Fixes: `Layout/TrailingWhitespace: Trailing whitespace detected.
See https://codeclimate.com/github/rails/rails/issues
Releted to b707a6d0eb7
|
| |
|
|\
| |
| | |
Add `Style/RedundantFreeze` to remove redudant `.freeze`
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Since Rails 6.0 will support Ruby 2.4.1 or higher
`# frozen_string_literal: true` magic comment is enough to make string object frozen.
This magic comment is enabled by `Style/FrozenStringLiteralComment` cop.
* Exclude these files not to auto correct false positive `Regexp#freeze`
- 'actionpack/lib/action_dispatch/journey/router/utils.rb'
- 'activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb'
It has been fixed by https://github.com/rubocop-hq/rubocop/pull/6333
Once the newer version of RuboCop released and available at Code Climate these exclude entries should be removed.
* Replace `String#freeze` with `String#-@` manually if explicit frozen string objects are required
- 'actionpack/test/controller/test_case_test.rb'
- 'activemodel/test/cases/type/string_test.rb'
- 'activesupport/lib/active_support/core_ext/string/strip.rb'
- 'activesupport/test/core_ext/string_ext_test.rb'
- 'railties/test/generators/actions_test.rb'
|
| | |
|
|/
|
|
| |
the parallel tests (#34030)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
In Ruby 2.3 or later, `String#+@` is available and `+@` is faster than `dup`.
```ruby
# frozen_string_literal: true
require "bundler/inline"
gemfile(true) do
source "https://rubygems.org"
gem "benchmark-ips"
end
Benchmark.ips do |x|
x.report('+@') { +"" }
x.report('dup') { "".dup }
x.compare!
end
```
```
$ ruby -v benchmark.rb
ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-linux]
Warming up --------------------------------------
+@ 282.289k i/100ms
dup 187.638k i/100ms
Calculating -------------------------------------
+@ 6.775M (± 3.6%) i/s - 33.875M in 5.006253s
dup 3.320M (± 2.2%) i/s - 16.700M in 5.032125s
Comparison:
+@: 6775299.3 i/s
dup: 3320400.7 i/s - 2.04x slower
```
|
|
|
|
|
|
|
|
|
|
|
|
| |
`finalize_compiled_template_methods`
Since we introduced default option for `class_attribute` and
`mattr_accessor` family of methods and changed all occurrences of setting
default values by using of `:default` option I think it would be fine to use
`:default` option in order to set default value of `finalize_compiled_template_methods`
since it expresses itself very well.
Related to #29294, #32418
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
ActionView::Template instances compile their source to methods on the
ActionView::CompiledTemplates module. To prevent leaks in development
mode, where templates can frequently change, a finalizer is added that
undefines these methods[1] when the templates are garbage-collected.
This is undesirable in the test environment, however, as templates don't
change during the life of the test. Moreover, the cost of undefining a
method is proportional to the number of descendants a class or module
has, since the method cache must be cleared for all descendant classes.
As ActionView::CompiledTemplates is mixed into every
ActionView::TestCase (or in RSpec suites, every view spec example
group), it can end up with a very large number of descendants, and
undefining its methods can become very expensive.
In large test suites, this results in a long delay at the end of the
test suite as all template finalizers are run, only for the process to
then exit.
To avoid this unnecessary cost, this change adds a config option,
`action_view.finalize_compiled_template_methods`, defaulting to true,
and sets it to false in the test environment only.
[1] https://github.com/rails/rails/blob/09b2348f7fc8d4e7191e70e06608c5909067e2aa/actionview/lib/action_view/template.rb#L118-L126
|
|
|
|
| |
We do not use double assign since 61f92f8bc5fa0b486fc56f249fa23f1102e79759.
|
|
|
|
| |
`def a() x = x = 1; end` warns since Ruby 2.5 (r59585)
|