Commit Graph

2461 Commits

Author SHA1 Message Date
Eugene Kenny 0b244ff44c
Merge pull request #39989 from jonathanhefner/translate-refactor
Improve Action View `translate` helper
2020-09-16 17:01:45 +01:00
Jonathan Hefner d81926fdac Improve Action View `translate` helper
This disentangles the control flow between Action View's `translate` and
I18n's `translate`.  In doing so, it fixes a handful of corner cases,
for which tests have now been added.  It also reduces memory
allocations, and improves speed when using a default:

**Memory**

```ruby
require "benchmark/memory"

Benchmark.memory do |x|
  x.report("warmup") { translate(:"translations.foo"); translate(:"translations.html") }
  x.report("text") { translate(:"translations.foo") }
  x.report("html") { translate(:"translations.html") }
  x.report("text 1 default") { translate(:"translations.missing", default: :"translations.foo") }
  x.report("html 1 default") { translate(:"translations.missing", default: :"translations.html") }
  x.report("text 2 defaults") { translate(:"translations.missing", default: [:"translations.missing", :"translations.foo"]) }
  x.report("html 2 defaults") { translate(:"translations.missing", default: [:"translations.missing", :"translations.html"]) }
end
```

Before:

```
                text     1.240k memsize (     0.000  retained)
                        13.000  objects (     0.000  retained)
                         2.000  strings (     0.000  retained)
                html     1.600k memsize (     0.000  retained)
                        19.000  objects (     0.000  retained)
                         2.000  strings (     0.000  retained)
      text 1 default     4.728k memsize (     1.200k retained)
                        39.000  objects (     4.000  retained)
                         5.000  strings (     0.000  retained)
      html 1 default     5.056k memsize (     1.160k retained)
                        41.000  objects (     3.000  retained)
                         4.000  strings (     0.000  retained)
     text 2 defaults     7.464k memsize (     2.392k retained)
                        54.000  objects (     6.000  retained)
                         4.000  strings (     0.000  retained)
     html 2 defaults     7.944k memsize (     2.384k retained)
                        60.000  objects (     6.000  retained)
                         4.000  strings (     0.000  retained)
```

After:

```
                text   952.000  memsize (     0.000  retained)
                         9.000  objects (     0.000  retained)
                         1.000  strings (     0.000  retained)
                html     1.008k memsize (     0.000  retained)
                        10.000  objects (     0.000  retained)
                         1.000  strings (     0.000  retained)
      text 1 default     2.400k memsize (    40.000  retained)
                        24.000  objects (     1.000  retained)
                         4.000  strings (     0.000  retained)
      html 1 default     2.464k memsize (     0.000  retained)
                        22.000  objects (     0.000  retained)
                         2.000  strings (     0.000  retained)
     text 2 defaults     3.232k memsize (     0.000  retained)
                        30.000  objects (     0.000  retained)
                         2.000  strings (     0.000  retained)
     html 2 defaults     3.456k memsize (     0.000  retained)
                        32.000  objects (     0.000  retained)
                         2.000  strings (     0.000  retained)
```

**Speed**

```ruby
require "benchmark/ips"

Benchmark.ips do |x|
  x.report("text") { translate(:"translations.foo") }
  x.report("html") { translate(:"translations.html") }
  x.report("text 1 default") { translate(:"translations.missing", default: :"translations.foo") }
  x.report("html 1 default") { translate(:"translations.missing", default: :"translations.html") }
  x.report("text 2 defaults") { translate(:"translations.missing", default: [:"translations.missing", :"translations.foo"]) }
  x.report("html 2 defaults") { translate(:"translations.missing", default: [:"translations.missing", :"translations.html"]) }
end
```

Before:

```
                text     35.685k (± 0.7%) i/s -    179.050k in   5.017773s
                html     28.569k (± 3.1%) i/s -    143.871k in   5.040128s
      text 1 default     13.953k (± 2.0%) i/s -     70.737k in   5.071651s
      html 1 default     12.507k (± 0.4%) i/s -     63.546k in   5.080908s
     text 2 defaults      9.103k (± 0.3%) i/s -     46.308k in   5.087323s
     html 2 defaults      8.570k (± 4.3%) i/s -     43.071k in   5.034322s
```

After:

```
                text     36.694k (± 2.0%) i/s -    186.864k in   5.094367s
                html     30.415k (± 0.5%) i/s -    152.900k in   5.027226s
      text 1 default     18.095k (± 2.7%) i/s -     91.086k in   5.036857s
      html 1 default     15.934k (± 1.7%) i/s -     80.223k in   5.036085s
     text 2 defaults     12.179k (± 0.6%) i/s -     61.659k in   5.062910s
     html 2 defaults     11.193k (± 2.1%) i/s -     56.406k in   5.041433s
```
2020-09-16 10:18:54 -05:00
Ryuta Kamizono c848baffd2 ✂️ [ci skip]
895134bcff (diff-7789e18ec0a61c6845755a257e6eb34fR3)
ee9e308f68 (diff-5e9551294914b338d923032fa904c6beR103)
5f63c771f7 (diff-600d5368b55e46ed961abb4295977ac3R506)
48b6bacbc5 (diff-279ac5c088a3ee7e9f954bbc10d1b773R246)
49adb7f4c6 (diff-0cbe7171fdd7821fd5836896849141c0R111)
9bfe89e68e (diff-9c1c95b001e3680ba8a473cf23508b68R8)
a0f18e6090 (diff-bef0ae2c16dacf77bfd2ba099af8a330R47)
8b4d344815 (diff-09660f59aee7ec893ad609315e8843c5R18)
49d1b5a98d (diff-531e71a9d5fdc8181f38ce4416553694R107)
b674f04756 (diff-7521c0bb452244663b689e77658e63e3R98)
a9012af688 (diff-60bdcf1e1954ec56d41fc4c7bd8d3e39R512)
6380aee182 (diff-5158c234d5e19bb1cffadcbc088400f1R262)
c7820d8124 (diff-f4614e7ba8081c0c9e20fe64b6374228R60)
8df7ed3b88 (diff-0495ed68f82d1bbde593ab5491eab24aR169)
6f94260ac6 (diff-7ecb6672f3fd37dfb79c4539395d3857R28)
03e44f9300 (diff-e9234c4c6668852448059c0a35840bcaR185)
2020-09-16 09:52:10 +09:00
Akira Matsuda 47f5459138 Module#const_set is a public method 2020-09-15 17:19:37 +09:00
Kasper Timm Hansen f04819972b
Merge pull request #40225 from p8/remove-unused-cache-hit-ivar
Remove unused @cache_hit Hash assignment
2020-09-13 12:35:18 +02:00
Petrik ebb83e46ba Remove unused @cache_hit Hash assignment
In 2abf6ca0c8 @cache_hit got introduced.
This was renamed to @cache_hits and revised in the subsequent commit
8240636bed but it seems one assignment was
overlooked.
2020-09-13 10:40:28 +02:00
Jonathan Hefner 98a76a50ed Refactor Action View `translate` helper
This refactor incidentally fixes a corner case when `translate` is
called with a block, the translation is missing, and
`debug_missing_translation` is false.

This commit adds a test for the above corner case, and additional tests
for existing behavior.
2020-09-11 11:56:17 -05:00
Jonathan Hefner e663f08446
Merge pull request from GHSA-cfjv-5498-mph5
Prior to this commit, when a translation key indicated that the
translation text was HTML, the value returned by `I18n.translate` would
always be marked as `html_safe`.  However, the value returned by
`I18n.translate` could be an untrusted value directly from
`options[:default]`.

This commit ensures values directly from `options[:default]` are not
marked as `html_safe`.
2020-09-09 14:41:31 -04:00
John Hawthorn 10df6931de
Merge pull request #40125 from jhawthorn/actionview_test_case_isolation
Use a unique controller class per ActionView::TestCase
2020-09-08 14:08:13 -07:00
John Hawthorn 3ec8ddd0cf Avoid module_eval on helpers from AV::TestCase
Previously we were using module_eval to manually add some helpers in
ActionView::TestCase, which assumes a lot about what _helpers allows.

Instead, we can use a standard helper block to define these methods only
one time, and add a method to the new uniq controller class to tie back
to the test instance.
2020-09-02 15:55:01 -07:00
John Hawthorn 65e42c91f5 Use unique controller per ActionView::TestCase
Previously the same class, ActionView::TestCase::TestController, was
used to build a controller for every ActionView::TestCase class.

This caused issues when helpers/helper methods were set directly on the
controller (which from one test we seem to want to support).

This commit solves this by creating a new controller class for every
test case, which gives the controller a unique set of helpers to work
with.

Co-authored-by: John Crepezzi <seejohnrun@github.com>
2020-09-02 15:55:01 -07:00
John Hawthorn 91ae9dfdee Don't override module name on AV::Base subclass
We should avoid overriding name if possible because it is confusing to
developers and it also can causes bugs in code which deal with modules
but aren't using the Module.instance_method(:name).bind workaround.

I believe we can achieve the desired "method missing" behaviour by just
redefining inspect.

Refs https://github.com/rails/rails/pull/39819
2020-09-02 14:47:07 -07:00
Rafael Mendonça França 0edc6c8f64
Remove unecessary method call
All branches that use translated_text are covered so we can remove this
method call.

Also apply some whitespaces around conditionals to make them explicit.
2020-08-26 20:46:33 +00:00
Sean Doyle 7cf52ae981
Extend `ActionView::Helpers#translate` to yield
This commit extends the `ActionView::Helpers#translate` (and by way of
alias, `#t`) helper methods to accept blocks.

When invoked with a block, the `translate` call will yield the
translated text as its first block argument, along with the resolved
translation key as its second:

```erb
<%= translate(".key") do |translation, resolved_key| %>
  <span data-i18n-key="<%= resolved_key %>"><%= translation %></span>
<% end %>
```

In cases where relative translation keys are foregone in lieu of fully
qualified keys, or if the caller is not interested in the resolved key,
the second block argument can be omitted:

```erb
<%= translate("action.template.key") do |translation| %>
  <p><%= translation %></p>
  <p><%= translation %>, but a second time</p>
<% end %>
```

A benefit of yielding the translation is that it enabled template-local
variable re-use. Alternatively, [`Object#tap`][tap] could be used.

Prior to this commit, however, the resolution of the translation key was
internal to `ActionView`, and unavailable to the caller (unless they
were willing to explicitly determine the resolved key themselves). By
making it available as a block parameter, it could be used to annotate
the translated value in the resulting elements.

[tap]: https://ruby-doc.org/core-2.7.0/Object.html#method-i-tap
2020-08-26 20:46:33 +00:00
Jonathan Fleckenstein 0b65e23978 Allow callers to remove nopush 2020-08-23 09:53:42 -04:00
Jonathan Fleckenstein 033ac18590 don't preload for defered scripts and disable push 2020-08-22 20:59:29 -04:00
nathanallen cd15412e5a fix documented default values for datetime_select view helper 2020-08-19 16:35:42 -07:00
Eileen M. Uchitelle 443c8470d1
Merge pull request #39939 from Shopify/link-preload-headers
Automatically set Link header for each stylesheet and script
2020-08-17 08:37:22 -04:00
Petrik a7ed92bd1d Use superclass name in inspect of ActionView::Base.with_empty_template_cache
When rendering views an anonymous subclass is created by calling
ActionView::Base.with_empty_template_cache.
This causes inspect to return an unhelpful description when calling
inspect:
`#<#<Class:0x012345012345>:<0x012345012345>`.

This can be confusing when exceptions are raised because it's hard to
figure out where to look. For example calling an undefined method in a
template would raise the following exception:

    undefined method `undefined' for #<#<Class:0x012345012345>:<0x012345012345>

Instead we can return the non-anonymous superclass name.

    undefined method `undefined' for #<ActionView::Base:0x01234502345>

The anonymous class is created in ActionView::Base.with_empty_template_cache.
See f9bea6304d
This seems to be done for performance reasons only, without expecting a
change to calling `inspect`.
2020-08-15 11:04:28 +02:00
Yasuo Honda 2d43d47786 Address `ArgumentError: Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true`
This pull request fixes #38697

It is caused by `@controller.singleton_class.include @routes.url_helpers` when `@controller` is nil in `ActionController::TestCase`.

* Without this commit

```ruby
% cd actionview
% PARALLEL_WORKERS=1 bin/test test/actionpack/controller/layout_test.rb test/template/url_helper_test.rb --seed 16702 -n "/^(?:LayoutSetInResponseTest#(?:test_layout_symbol_set_in_controller_returning_nil_falls_back_to_default)|UrlHelperTest#(?:test_url_for_with_array_and_only_path_set_to_false))$/"

Run options: --seed 16702 -n "/^(?:LayoutSetInResponseTest#(?:test_layout_symbol_set_in_controller_returning_nil_falls_back_to_default)|UrlHelperTest#(?:test_url_for_with_array_and_only_path_set_to_false))$/"

.E

Error:
UrlHelperTest#test_url_for_with_array_and_only_path_set_to_false:
ArgumentError: Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true
    /Users/yahonda/src/github.com/rails/rails/actionpack/lib/action_dispatch/http/url.rb:64:in `full_url_for'
    /Users/yahonda/src/github.com/rails/rails/actionpack/lib/action_dispatch/http/url.rb:54:in `url_for'
    /Users/yahonda/src/github.com/rails/rails/actionpack/lib/action_dispatch/routing/route_set.rb:333:in `block in <class:RouteSet>'
    /Users/yahonda/src/github.com/rails/rails/actionpack/lib/action_dispatch/routing/route_set.rb:838:in `url_for'
    /Users/yahonda/src/github.com/rails/rails/actionpack/lib/action_dispatch/routing/route_set.rb:270:in `call'
    /Users/yahonda/src/github.com/rails/rails/actionpack/lib/action_dispatch/routing/route_set.rb:213:in `call'
    /Users/yahonda/src/github.com/rails/rails/actionpack/lib/action_dispatch/routing/route_set.rb:326:in `block in define_url_helper'
    /Users/yahonda/src/github.com/rails/rails/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb:233:in `polymorphic_method'
    /Users/yahonda/src/github.com/rails/rails/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb:116:in `polymorphic_url'
    /Users/yahonda/src/github.com/rails/rails/actionview/lib/action_view/routing_url_for.rb:104:in `url_for'
    /Users/yahonda/src/github.com/rails/rails/actionview/test/template/url_helper_test.rb:102:in `test_url_for_with_array_and_only_path_set_to_false'

bin/test test/template/url_helper_test.rb:100

Finished in 0.042275s, 47.3093 runs/s, 47.3093 assertions/s.
2 runs, 2 assertions, 0 failures, 1 errors, 0 skips
%
```
2020-08-12 19:43:02 +09:00
Yasuo Honda 1e84ac4290 Clear Resolvers' cache after AVLogSubscriberTest tests
Addresses the build failure below:
https://buildkite.com/rails/rails/builds/70853#29647167-4db2-4810-810e-d2c3a4e6dcf8

* This pull request addresses this error.

```
$ bin/test test/template/log_subscriber_test.rb test/template/test_case_test.rb -n "/^(?:AVLogSubscriberTest#(?:test_render_collection_template)|ActionView::HelperInclusionTest#(?:test_helper_class_that_is_being_tested_is_always_included_in_view_instance))$/" --seed 54118
Run options: -n "/^(?:AVLogSubscriberTest#(?:test_render_collection_template)|ActionView::HelperInclusionTest#(?:test_helper_class_that_is_being_tested_is_always_included_in_view_instance))$/" --seed 54118

.E

Error:
ActionView::HelperInclusionTest#test_helper_class_that_is_being_tested_is_always_included_in_view_instance:
ActionView::Template::Error: undefined method `_test__customer_erb___3224798146126036163_10260' for #<#<Class:0x00005653f1b35768>:0x00005653f1b348e0>
    /home/yahonda/src/github.com/rails/rails/actionview/lib/action_view/base.rb:276:in `_run'
    /home/yahonda/src/github.com/rails/rails/actionview/lib/action_view/template.rb:182:in `block in render'
    /home/yahonda/src/github.com/rails/rails/activesupport/lib/active_support/notifications.rb:205:in `instrument'
    /home/yahonda/src/github.com/rails/rails/actionview/lib/action_view/template.rb:384:in `instrument_render_template'
    /home/yahonda/src/github.com/rails/rails/actionview/lib/action_view/template.rb:180:in `render'
    /home/yahonda/src/github.com/rails/rails/actionview/lib/action_view/renderer/collection_renderer.rb:186:in `block in collection_with_template'
    /home/yahonda/src/github.com/rails/rails/actionview/lib/action_view/renderer/collection_renderer.rb:66:in `block in each_with_info'
    /home/yahonda/src/github.com/rails/rails/actionview/lib/action_view/renderer/collection_renderer.rb:66:in `each'
    /home/yahonda/src/github.com/rails/rails/actionview/lib/action_view/renderer/collection_renderer.rb:66:in `each_with_info'
    /home/yahonda/src/github.com/rails/rails/actionview/lib/action_view/renderer/collection_renderer.rb:177:in `each'
    /home/yahonda/src/github.com/rails/rails/actionview/lib/action_view/renderer/collection_renderer.rb:177:in `map'
    /home/yahonda/src/github.com/rails/rails/actionview/lib/action_view/renderer/collection_renderer.rb:177:in `collection_with_template'
    /home/yahonda/src/github.com/rails/rails/actionview/lib/action_view/renderer/collection_renderer.rb:159:in `block (2 levels) in render_collection'
    /home/yahonda/src/github.com/rails/rails/actionview/lib/action_view/renderer/partial_renderer/collection_caching.rb:21:in `cache_collection_render'
    /home/yahonda/src/github.com/rails/rails/actionview/lib/action_view/renderer/collection_renderer.rb:158:in `block in render_collection'
    /home/yahonda/src/github.com/rails/rails/activesupport/lib/active_support/notifications.rb:203:in `block in instrument'
    /home/yahonda/src/github.com/rails/rails/activesupport/lib/active_support/notifications/instrumenter.rb:24:in `instrument'
    /home/yahonda/src/github.com/rails/rails/activesupport/lib/active_support/notifications.rb:203:in `instrument'
    /home/yahonda/src/github.com/rails/rails/actionview/lib/action_view/renderer/collection_renderer.rb:144:in `render_collection'
    /home/yahonda/src/github.com/rails/rails/actionview/lib/action_view/renderer/collection_renderer.rb:116:in `render_collection_with_partial'
    /home/yahonda/src/github.com/rails/rails/actionview/lib/action_view/renderer/renderer.rb:75:in `render_partial_to_object'
    /home/yahonda/src/github.com/rails/rails/actionview/lib/action_view/renderer/renderer.rb:27:in `render_to_object'
    /home/yahonda/src/github.com/rails/rails/actionview/lib/action_view/renderer/renderer.rb:22:in `render'
    /home/yahonda/src/github.com/rails/rails/actionview/lib/action_view/helpers/rendering_helper.rb:38:in `block in render'
    /home/yahonda/src/github.com/rails/rails/actionview/lib/action_view/base.rb:306:in `in_rendering_context'
    /home/yahonda/src/github.com/rails/rails/actionview/lib/action_view/helpers/rendering_helper.rb:34:in `render'
    /home/yahonda/src/github.com/rails/rails/actionview/lib/action_view/test_case.rb:205:in `render'
    /home/yahonda/src/github.com/rails/rails/actionview/test/template/test_case_test.rb:126:in `render_from_helper'
    /home/yahonda/src/github.com/rails/rails/actionview/test/fixtures/test/_from_helper.erb:1:in `__home_yahonda_src_github_com_rails_rails_actionview_test_fixtures_test__from_helper_erb___900298654238864924_10340'
    /home/yahonda/src/github.com/rails/rails/actionview/lib/action_view/base.rb:276:in `_run'
    /home/yahonda/src/github.com/rails/rails/actionview/lib/action_view/template.rb:182:in `block in render'
    /home/yahonda/src/github.com/rails/rails/activesupport/lib/active_support/notifications.rb:205:in `instrument'
    /home/yahonda/src/github.com/rails/rails/actionview/lib/action_view/template.rb:384:in `instrument_render_template'
    /home/yahonda/src/github.com/rails/rails/actionview/lib/action_view/template.rb:180:in `render'
    /home/yahonda/src/github.com/rails/rails/actionview/lib/action_view/renderer/partial_renderer.rb:285:in `block in render_partial_template'
    /home/yahonda/src/github.com/rails/rails/activesupport/lib/active_support/notifications.rb:203:in `block in instrument'
    /home/yahonda/src/github.com/rails/rails/activesupport/lib/active_support/notifications/instrumenter.rb:24:in `instrument'
    /home/yahonda/src/github.com/rails/rails/activesupport/lib/active_support/notifications.rb:203:in `instrument'
    /home/yahonda/src/github.com/rails/rails/actionview/lib/action_view/renderer/partial_renderer.rb:280:in `render_partial_template'
    /home/yahonda/src/github.com/rails/rails/actionview/lib/action_view/renderer/partial_renderer.rb:271:in `render'
    /home/yahonda/src/github.com/rails/rails/actionview/lib/action_view/renderer/renderer.rb:84:in `render_partial_to_object'
    /home/yahonda/src/github.com/rails/rails/actionview/lib/action_view/renderer/renderer.rb:27:in `render_to_object'
    /home/yahonda/src/github.com/rails/rails/actionview/lib/action_view/renderer/renderer.rb:22:in `render'
    /home/yahonda/src/github.com/rails/rails/actionview/lib/action_view/helpers/rendering_helper.rb:38:in `block in render'
    /home/yahonda/src/github.com/rails/rails/actionview/lib/action_view/base.rb:306:in `in_rendering_context'
    /home/yahonda/src/github.com/rails/rails/actionview/lib/action_view/helpers/rendering_helper.rb:34:in `render'
    /home/yahonda/src/github.com/rails/rails/actionview/lib/action_view/test_case.rb:205:in `render'
    /home/yahonda/src/github.com/rails/rails/actionview/lib/action_view/test_case.rb:122:in `render'
    /home/yahonda/src/github.com/rails/rails/actionview/test/template/test_case_test.rb:136:in `block in <class:HelperInclusionTest>'

bin/test test/template/test_case_test.rb:132

Finished in 0.076637s, 26.0970 runs/s, 39.1454 assertions/s.
2 runs, 3 assertions, 0 failures, 1 errors, 0 skips
$
```

Refer #36189 for the similar fix
2020-07-30 12:14:10 +09:00
Jean Boussier a9012af688 Automatically set Link header for each stylesheet and script
<link rel="preload"> elements[0] can be serialized in `Link`
headers[1] to allow the browser to preload them before
it parsed the HTML body.

It is particularly useful for scripts included at the bottom
of the document.

[0] https://developer.mozilla.org/en-US/docs/Web/HTML/Preloading_content
[1] https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Link
2020-07-28 11:57:36 +02:00
Jonathan Hefner e6950a332a Add label attribute to <option> from include_blank
The `:include_blank` option of various `<select>`-related helpers causes
an `<option>` element with no content to be rendered.  However, the
[HTML spec] says that unless an `<option>` element has a `label`
attribute (which must be non-empty), its content must be "Text that is
not inter-element whitespace."

In #24923, this issue was addressed for `select_tag` by adding a `label`
attribute to the `<option>`.  This commit addresses the issue in the
same manner for `FormBuilder#select` and various date / time select
helpers.

[HTML spec]: https://html.spec.whatwg.org/multipage/form-elements.html#the-option-element
2020-07-24 15:45:18 -05:00
Jean Boussier 12f3f11f61 Use URI::DEFAULT_PARSER rather than instantiate a new one 2020-06-29 23:06:34 +02:00
pavel a4583da838 simplify conversion to BINARY 2020-06-24 19:51:20 +02:00
Ross Kaffenberger 04cbaa1475 Use ES module syntax for application.js.tt and docs
This change swaps the CommonJS require() syntax in the Webpacker
application.js pack template file and in documentation examples with ES
module import syntax.

Benefits of this change include:

Provides continuity with the larger frontend community: Arguably, one of
the main draws in adopting Webpacker is its integration with Babel to
support ES module syntax. For a fresh Rails install with Webpacker, the
application.js file will be the first impression most Rails developers
have with webpack and Webpacker.  Most of the recent documentation and
examples they will find online for using other libraries will be based
on ES module syntax.

Reduces confusion: Developers commonly add ES imports to their
application.js pack, typically by following online examples, which means
mixing require() and import statements in a single file. This leads to
confusion and unnecessary friction about differences between require()
and import.

Embraces browser-friendliness: The ES module syntax forward-looking and
is meant to be supported in browsers. On the other hand, require()
syntax is synchronous by design and not browser-supported as CommonJS
originally was adopted in Node.js for server-side JavaScript. That
webpack supports require() syntax is merely a convenience.

Encourages best practices regarding optimization: webpack can statically
analyze ES modules and "tree-shake", i.e., strip out unused exports from
the final build (given certain conditions are met, including
`sideEffects: false` designation in package.json).
2020-06-16 15:12:12 -04:00
Ryuta Kamizono 528b62e386 Address to false negative for Performance/DeletePrefix,DeleteSuffix
Follow up to c07dff7227.

Actually it is not the cop's fault, but we mistakenly use `^`, `$`, and
`\Z` in much places, the cop doesn't correct those conservatively.

I've checked all those usage and replaced all safe ones.
2020-06-14 13:04:47 +09:00
Ryuta Kamizono cfb7c16ac4 Fixup CHANGELOGs [ci skip] 2020-06-07 12:58:22 +09:00
Jonathan Hefner 08aeb01b0f Lazily build path regex in PathParser
Eagerly building the path regex can exclude handlers which are added on
Action View load.

Fixes #39492.
2020-05-31 15:28:24 -05:00
Eugene Kenny 5888c359e4 Add test for HTML format fallback from JS template
When rendering a template with an explicit JS format, typically via
`respond_to :js`, we want to be able to render HTML partials without
having to specify their format, in order to make SJR more ergonomic.
2020-05-29 22:07:17 +01:00
Ryuta Kamizono c65864cdca Prefer no allocation `start/end_with?` over `String#[] ==` 2020-05-29 10:20:13 +09:00
Eugene Kenny 8ae6626b65 Override clear_cache in custom path resolver
https://buildkite.com/rails/rails/builds/69620#ffaa78f1-aba4-42b9-91c8-0fe5d333263a

Since 096d143c8c, when the tests run in
parallel it's possible for `ActionView::LookupContext::DetailsKey.clear`
to be called while this test is running, which wouldn't work correctly.
2020-05-27 21:07:58 +01:00
John Hawthorn db543ba728
Merge pull request #39361 from jhawthorn/path_parser
Introduce Resolver::PathParser
2020-05-26 20:16:18 -07:00
Aaron Lipman dd7a673782
Remove redundant @virtual_path variable
Following the introduction of the @current_template variable in 1581cab,
the @virtual_path variable is now redundant, as the value of the virtual
path may be accessed via @current_template.virtual_path. This commit
removes @virtual_path and replaces any references to @virtual_path with
@current_template.virtual_path.
2020-05-26 15:53:11 -04:00
Aaron Lipman 4671fe2040
Ensure cache fragment digests include all templates
A Rails view may rely on several templates (e.g. layouts and partials)
in addition to the template for the action being rendered (e.g.
"show.html.erb"). To track which view file is currently being rendered
for the purpose of generating template tree digests used in cache
fragment keys, Action View uses a stack, the top item of which is
accessed via the @current_template variable (introduced in 1581cab).

Consider the following template:

    <!-- home.html.erb -->
    <%= render layout: "wrapper" do %>
      <%= cache "foo" %>
        HOME
      <%= end %>
    <%= end %>

Inside the block passed to the render helper, @current_template
corresponds to the wrapper.html.erb template instead of home.html.erb.
As wrapper.html.erb is then used as the root node for generating the
template tree digest used in the cache fragment key, the cache fragment
fails to expire upon changes to home.html.erb. Additionally, should a
second template use the wrapper.html.erb layout and contain a cache
fragment with the same key, the cache fragment keys for both templates
will be identical - causing cached content to "leak" from one view to
another (as described in #38984).

This commit skips adding templates to the stack when rendered as a
layout with a block via the render helper, ensuring correct and unique
cache fragment digests. Additionally, the virtual_path keyword arguments
found in CacheHelper and all references to the are removed as they no
longer possess any function. (Following the introduction of
@current_template, virtual_path is accessed via
@current_template.virtual_path rather than as a standalone variable.)
2020-05-26 15:52:05 -04:00
swaggermeister 2a1ec6ed35
Fix typo 2020-05-25 15:00:18 -04:00
Ryuta Kamizono dc94a753d1 require "active_support/core_ext/symbol/starts_ends_with" for Ruby 2.6
And use `Symbol#[]` to strip suffix to avoid intermediate string
allocation.
2020-05-25 05:24:44 +09:00
Jonathan Hefner a2ca8f062c Utilize Symbol#start_with? and #end_with?
Follow-up to #39155.

Thanks to Symbol#start_with? and #end_with?, these calls no longer need
to be prefixed with `.to_s`.
2020-05-24 14:46:12 -05:00
fatkodima e24d6ecbfd Update rubocop-performance gem and enable Performance/DeletePrefix and Performance/DeleteSuffix cops 2020-05-24 12:51:35 +03:00
Vinicius Stock 732372c928
Reduce allocations in action_view cache expiry 2020-05-22 18:38:56 -04:00
Jonathan Hefner cd2b3be9a6 Allow Erubi bufvar to be configured
This allows `render_in` components that compile their own templates to
use their view context's current output buffer while a
`with_output_buffer` block is being evaluated.

Partially addresses #39377.
2020-05-21 15:22:51 -05:00
John Hawthorn 827119c48b Mark PathParser as :nodoc: 2020-05-19 18:58:44 -07:00
John Hawthorn e53c45b80c Introduce Resolver::PathParser
The template resolver is supposed to determine the handler, format, and
variant from the path in extract_handler_and_format_and_variant.

Previously this behaviour was close but didn't exactly match the
behaviour of finding templates, and in some cases (particularly with
handlers or formats missing) would return incorrect results.

This commit introduces Resolver::PathParser, a class which should be
able to accurately from any path inside a view directory be able to tell
us exactly the prefix, partial, variant, locale, format, variant, and
handler of that template.

This works by building a building a regexp from the known handlers and
file types. This requires that any resolvers have their cache cleared
when new handlers or types are registered (this was already somewhat the
requirement, since resolver lookups are cached, but this makes it
necessary in more situations).
2020-05-19 18:55:10 -07:00
John Hawthorn 8762d93afc Add tests of resolver variant handling
The template resolver is supposed to determine the handler, format, and
variant from the path in extract_handler_and_format_and_variant.

This commit adds tests for how variants are parsed from the filenames
found in the resolver. It includes two skipped tests which currently fail.
2020-05-19 18:55:10 -07:00
John Hawthorn dc778f83d7 Only use valid handlers in resolver_shared_tests
We don't have jbuilder installed (this would work if it was).
2020-05-19 18:55:10 -07:00
fatkodima 6c4f3be929 Unify raise_on_missing_translations for views and controllers 2020-05-20 02:42:59 +03:00
Rafael França a80115b7c5
Merge pull request #39204 from prathamesh-sonpatki/template-annotation
Add the configuration option for annotating templates with file names to the generated app
2020-05-19 19:11:31 -04:00
Prathamesh Sonpatki a673ce69e7
Rename `annotate_template_file_names` to `annotate_rendered_view_with_filenames`
- Add the configuration option for annotating templates with file names to the generated app.
- Add `annotate_rendered_view_with_filenames` option to configuring guide.
2020-05-19 09:28:14 +05:30
Aaron Patterson b472feddbc
Merge branch 'master-sec'
* master-sec:
  Check that request is same-origin prior to including CSRF token in XHRs
  HMAC raw CSRF token before masking it, so it cannot be used to reconstruct a per-form token
  activesupport: Avoid Marshal.load on raw cache value in RedisCacheStore
  activesupport: Avoid Marshal.load on raw cache value in MemCacheStore
  Return self when calling #each, #each_pair, and #each_value instead of the raw @parameters hash
  Include Content-Length in signature for ActiveStorage direct upload
2020-05-18 08:48:41 -07:00
John Hawthorn d6a01650aa Skip interpolated strings in AV::Digestor 2020-05-17 15:06:17 -07:00