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
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.)
- Add the configuration option for annotating templates with file names to the generated app.
- Add `annotate_rendered_view_with_filenames` option to configuring guide.
As a developer, when looking at a page in my web browser, it's sometimes
difficult to figure out which template(s) are being used to render the page.
config.action_view.annotate_template_file_names adds HTML comments to the
rendered output indicating where each template begins and ends.
Co-authored-by: Aaron Patterson <tenderlove@github.com>
Adds support for conditional values to TagBuilder,
extracting logic we use in the GitHub application,
inspired by https://github.com/JedWatson/classnames.
It’s common practice to conditionally apply CSS classes
in Rails views. This can lead to messy string interpolation,
often using ternaries:
```ruby
content_tag(
"My username",
class: "always #{'sometimes' if current_user.special?} another"
)
```
By adding support for hashes to TagBuilder, we can instead write the following:
```ruby
content_tag(
"My username",
class: ["always", "another", { 'sometimes' => current_user.special? }]
)
```
cc @JedWatson
* Added a phone_to helper method, on the style of mail_to and sms_to.
It creates an anchor tag with the href set to tel: *here your number*
which, when clicked on a mobile phone, or on a desktop with a supported
application, lets the phone app kick in, and it prepopulates it with the
phone number specified.
[Pietro Moro + Rafael Mendonça França]
The source_extract method will return nil when it can't find the file name in
the backtrace, methods that consume this method expect an array and the nil ends
up causing type errors down the road like it happened here: #36341. This
patch refactors the source_extract method so that it returns an empty
array instead of nil when it can't find the source code.
Co-authored-by: Kasper Timm Hansen <kaspth@gmail.com>
When a SyntaxError is detected in a template we raise this exception. On
a first request to the server the exception we get a NameError since the
exception is not required from `active_view/template/error.rb` yet.
However later on it gets required and a second request will succeed.
On the first request we see the rails "Something Wen Wrong" page and not
the expected syntax error in template error page with the webconsole and
stacktrace. By autoloading the constant we fix this issue.
Co-authored-by: Gannon McGibbon <gannon.mcgibbon@gmail.com>
The `#csrf_meta_tags` and `#token_tag` Action View helper methods are
expecting the class in which are included to explicitly define the
method `#protect_against_forgery?` or else they will fail with
`NoMethodError`.
This is a problem if you want to use Action View outside of Rails
applications. For example, in #34788 I used the `#button_to` helper
inside of the error pages templates that have a custom
`ActionView::Base` subclass, which did not defined
`#protect_against_forgery?` and trying to call the button failed.
I had to dig inside of Action View to find-out what's was going on. I
think we should either set a default method implementation in the
helpers or check for the method definition, but don't explicitly require
the presence of `#protect_against_forgery?` in every `ActionViews::Base`
subclass as the errors are hard to figure out.
Generally followed the pattern for https://github.com/rails/rails/pull/32034
* Removes needless CI configs for 2.4
* Targets 2.5 in rubocop
* Updates existing CHANGELOG entries for fewer merge conflicts
* Removes Hash#slice extension as that's inlined on Ruby 2.5.
* Removes the need for send on define_method in MethodCallAssertions.