1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00
Commit graph

1775 commits

Author SHA1 Message Date
Ryuta Kamizono
2b0b5a75c0 Bump license years to 2021 [ci skip] 2021-01-01 12:21:20 +09:00
Marek Kasztelnik
8e53f9178c Revert "Remove redundant @virtual_path variable"
This reverts commit dd7a673782.
2020-12-30 14:07:09 +01:00
Rafael França
88ef9b2276
Merge pull request from kylekeesling/master
Update`form_with` and`form_for` API documentation to reflect new local method default [ci skip]
2020-12-29 17:54:40 -05:00
Kyle Keesling
3aef59cae2
Update form_with and form_for documentation to reflect new non-remote defaults in 6.1 2020-12-29 07:28:13 -05:00
Sean Doyle
9af9458396 Consistently render button_to as <button>
Prior to this commit, the
[ActionView::Helpers::UrlHelper#button_to][button_to] helper rendered
`<input type="submit">` elements when passed its contents as a String
argument, and rendered `<button type="submit">` elements when passed its
contents as a block.

This difference is subtle, and might lead to surprises.

Additionally, a `<form>` element's submitter can encode a `name`/`value`
pairing, which will be submitted as part of the request. When
`button_to` renders an `<input type="submit">` element, the "button"
content is rendered as a `[value]` attribute, which prevents any
meaningful data from being encoded.

Since it's a single `<button>` or `<input type="submit">` within a
`<form>`, missing out on that opportunity to encode information might
not be a show stopper, but ensuring that a `<button>` element is
rendered _without_ a default `[value]` attribute enables applications to
encode additional information that can be accessed JavaScript as
`element.value`, instead of a workaround like
`element.getAttribute("data-value")`.

Support rendering `input` elements with button_to
---

To support the original behavior of `button_to` rendering `<input
type="submit">` elements when invoked _without_ a block, expose the
`app.config.button_to_generates_button_tag` configuration flag.

By default, it's set to `true` and ensures that all `button_to` calls
render `<button>` elements. To revert to the original behavior, set it
to `false`.

[button_to]: https://api.rubyonrails.org/v6.0/classes/ActionView/Helpers/UrlHelper.html#method-i-button_to

Co-authored-by: Dusan Orlovic <duleorlovic@gmail.com>
2020-12-28 19:33:05 -05:00
Eugene Kenny
f3071970c2
Merge pull request from tgxworld/speed_up_text_helper_excerpt
Improve perf of `ActionView::Helpers::TextHelper#excerpt` for large strings.
2020-12-27 20:03:46 +00:00
Guo Xiang Tan
a40d3debe8
Improve perf of ActionView::Helpers::TextHelper#excerpt for large strings. 2020-12-23 16:20:10 +08:00
Andrew White
71bc41477d
Merge pull request from rails/add-preload-links-header-config
Add `config.action_view.preload_links_header` option
2020-12-21 06:41:13 +00:00
Andrew White
200083c232
Add config.action_view.preload_links_header option
PR  added support for the `Link` header being generated
automatically when using `stylesheet_link_tag` and
`javascript_include_tag`. However not everything should be
preloaded, e.g. a link to a legacy IE stylesheet has no need to be
preloaded because IE doesn't support the header and in some browsers it
will trigger the preload even though it's not used since it's inside an
IE conditional comment. This leads to increased bandwith costs and
slower application performance.

To allow more flexibility for sites that may have complex needs for the
`Link` header this commit adds a configuration option that disables it
completely and leaves it up to the application to decide how to handle
generating a `Link` header.
2020-12-19 05:24:09 +00:00
aaron
432698ef2b
Fix SELECT COUNT queries when rendering ActiveRecord collections ()
* Fix `SELECT COUNT` queries when rendering ActiveRecord collections

Fixes 

When rendering collections, calling `size` when the collection is an
ActiveRecord relation causes unwanted `SELECT COUNT(*)` queries. This
change ensures the collection is an array before getting the size, and
also loads the relation for any further array inspections.

* Test queries when rendering relation collections

* Add `length` support to partial collection iterator

Allows getting the size of a relation without duplicating records, but
still loads the relation. The length method existence needs to be
checked because you can pass in an `Enumerator`, which does not respond
to `length`.

* Ensure unsubscribed from notifications after tests

[Rafael Mendonça França + aar0nr]
2020-12-18 15:58:11 -05:00
Kasper Timm Hansen
3d46ca9c0a
Merge pull request from vinistock/save_allocations_in_digest
Save some allocations in ActionView digest
2020-12-18 20:02:59 +01:00
Rafael França
9c79623ce9
Merge pull request from jonathanhefner/config-action_view-image_decoding
Add config.action_view.image_decoding
2020-12-16 20:20:22 -05:00
Rafael França
faa27ddafc
Merge pull request from Shopify/link-preload-integrity
Link preloading should keep integrity hashes in the header
2020-12-16 19:58:35 -05:00
Étienne Barrié
4aa91262f0 Link preloading should keep integrity hashes in the header
When a stylesheet or javascript link tag (or preload link tag) is output
in the view, it also gets sent as a Link header for preloading. This
Link header is missing the integrity attribute even when one is set on
the tag, which prevents the browser from using the preloaded resource.

Co-authored-by: Adrianna Chang <adrianna.chang@shopify.com>
2020-12-14 15:50:26 -05:00
Jonathan Hefner
48c1bc2f65 Add config.action_view.image_decoding
This adds `Rails.application.config.action_view.image_decoding` to
configure the default value of the `image_tag` `:decoding` option.
2020-12-14 11:45:48 -06:00
Jonathan Hefner
b8b18bbfad Handle nil translation key
`I18n.translate` returns `nil` when given a `nil` key, *unless* a
`default` is also specified.  If a `default` is specified, the `nil` key
is treated as a missing key.

In Rails 6.0, the `translate` helper always returned `nil` when given a
`nil` key.  After , the `translate` helper always raised an
`I18n::ArgumentError` when given a `nil` key.  This commit fixes the
`translate` helper to mirror the `I18n.translate` behavior when given a
`nil` key, with and without a `default`.
2020-12-10 11:51:32 -06:00
Rafael Mendonça França
b178a92428
Refactoring the code to avoid some conditionals 2020-12-09 18:46:45 +00:00
Rafael França
e0a362c138
Merge pull request from igor04/disable_with_and_automatically_disable_submit_tag
Do not use submit_tag auto-disabling when disable_with is set to false
2020-12-09 13:38:44 -05:00
Jonathan Hefner
2c555c8d60 Convert translation key to string as necessary
Follow-up to .

`I18n.translate` converts the initial key (but not `default` keys) to a
string before performing a lookup.  For parity, we should do the same.
2020-12-09 11:49:29 -06:00
Rafael França
3c2a80d8b1
Merge pull request from jonathanhefner/config-action_view-image_loading
Add config.action_view.image_loading
2020-12-08 19:10:22 -05:00
Taufiq Muhammadi
a911dd0e08
Call class method since sanitizer's instance method is private and add tests
revert back to earlier version that call class method of class
returned by #sanitizer_vendor.safe_list_sanitizer
2020-12-08 22:32:49 +00:00
KapilSachdev
a908d06c85
feat(rubocop): Add Style/RedundantRegexpEscape
- This cop will help in removing unnecessary escaping inside Regexp literals.
2020-12-08 18:57:09 +00:00
Jonathan Hefner
926129a28b Add config.action_view.image_loading
Browser native support for lazy loading images is now a part of the
official HTML standard.  To indicate to the browser that an image should
be lazily loaded, add the `loading="lazy"` attribute to the `img` tag.
Or, in Rails parlance, add the `loading: "lazy"` option to the
`image_tag` call.

This commit adds `Rails.application.config.action_view.image_loading` to
configure the default value of the `image_tag` `:loading` option.  Thus
by setting `config.action_view.image_loading = "lazy"`, an application
can opt in to lazy loading images sitewide, without changing view code.
2020-12-05 10:06:09 -06:00
Rafael Mendonça França
59f7f5889e
Start Rails 6.2 development 🎉 2020-12-03 01:35:29 +00:00
Sean Doyle
59ca21c011 Declare ActionView::Helpers::FormBuilder#id
`ActionView::Helpers::FormBuilder#id`
---

Generate an HTML `id` attribute value.

Return the [`<form>` element's][mdn-form] `id` attribute.

```html+erb
<%= form_for @post do |f| %>
  <%# ... %>

  <% content_for :sticky_footer do %>
    <%= form.button(form: f.id) %>
  <% end %>
<% end %>
```

In the example above, the `:sticky_footer` content area will exist
outside of the `<form>` element. [By declaring the `form` HTML
attribute][mdn-button-attr-form], we hint to the browser that the
generated `<button>` element should be treated as the `<form>` element's
submit button, regardless of where it exists in the DOM.

[A similar pattern could be used for `<input>`
elements][mdn-input-attr-form] (or other form controls) that do not
descend from the `<form>` element.

`ActionView::Helpers::FormBuilder#field_id`
---

Generate an HTML <tt>id</tt> attribute value for the given field

Return the value generated by the <tt>FormBuilder</tt> for the given
attribute name.

```html+erb
<%= form_for @post do |f| %>
  <%= f.label :title %>
  <%= f.text_field :title, aria: { describedby: form.field_id(:title, :error) } %>
  <span id="<%= f.field_id(:title, :error) %>">is blank</span>
<% end %>
```

In the example above, the <tt><input type="text"></tt> element built by
the call to <tt>FormBuilder#text_field</tt> declares an
<tt>aria-describedby</tt> attribute referencing the <tt><span></tt>
element, sharing a common <tt>id</tt> root (<tt>post_title</tt>, in this
case).

This method is powered by the `field_id` helper declared in
`action_view/helpers/form_tag_helper`, which is made available for
general template calls, separate from a `FormBuilder` instance.

[mdn-form]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form
[mdn-button-attr-form]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#attr-form
[mdn-input-attr-form]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-form
[mdn-aria-describedby]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-describedby_attribute
[w3c-wai]: https://www.w3.org/WAI/tutorials/forms/notifications/#listing-errors
2020-11-30 18:47:49 -05:00
Sean Doyle
7503ef9490
Escape HTML attributes for ERB interpolation ()
Transforms a Hash into HTML Attributes, ready to be interpolated into
ERB.

```html+erb
<input <%= tag.attributes(type: :text, aria: { label: "Search" }) %> >
<%# => <input type="text" aria-label="Search"> %>
```

Utilizes the `ActionView::Helpers::TagHelper#tag_options` implementation
to enable combining ERB with attribute transformation, without requiring
templates to replace HTML strings with `tag` or `content_tag`
invocations.

Co-authored-by: David Heinemeier Hansson <david@loudthinking.com>
2020-11-28 11:01:15 +01:00
Sean Doyle
d2e07395b3 ActionView: Serialize Regexp into HTML attribute
When serializing a Regexp instance, encode the [Regexp#source][]. When
encoding a value into a [pattern][] attribute from ERB/Ruby, declaring
the String can be tedious. For example, one might attempt to encode
`\w+` as `"\\\w+"`, but once serialized to the browser, that is not
equivalent to the `"\w+"` HTML attribute.

Instead, enable declaring Regexp and Regexp literals as attributes, and
encoding them as their source String.

[Regexp#source]: https://ruby-doc.org/core-2.7.2/Regexp.html#method-i-source
[pattern]: https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern
2020-11-26 17:52:26 -05:00
Akira Matsuda
bc551bfcb1 TagHelper uses Enumerable#index_with 2020-11-27 00:21:42 +09:00
Akira Matsuda
7a8c1f52d6 Simply require rather than autoload + immediately load below
also, requires are sorted a little bit along with the dependency orders
2020-11-26 23:27:22 +09:00
Akira Matsuda
02bfb03c8e Missing requires 2020-11-26 23:27:22 +09:00
Akira Matsuda
16c866ed2c FormOptionsHelper does not depend on FormHelper 2020-11-26 23:27:22 +09:00
Akira Matsuda
3b8b01b23c UrlHelper does not depend on anything from javascript_helper.rb 2020-11-26 23:27:22 +09:00
Akira Matsuda
796a730dff These helpers do not use anything in tag_helper.rb 2020-11-26 23:27:22 +09:00
Akira Matsuda
6f938be763 ActionView::Helpers::AssetTagHelper uses no AS::Concern feature 2020-11-26 19:10:39 +09:00
Akira Matsuda
7afd2f1a71 AV::Helpers::TagHelper uses no AS::Concern feature 2020-11-26 01:37:55 +09:00
Balazs Varga
f4a6225357 Fix text_field_tag's placeholder documentation [ci skip]
When placeholder set to true on `text_field_tag`, it will try to look up its value from the translation files.
The documentation referenced an incorrect translation key scope, it is defined in [Placeholderable][1] as `helpers.placeholder` (singular).
Followup for 

Also improves wording.

[1]: 4640cff2b2/actionview/lib/action_view/helpers/tags/placeholderable.rb
2020-11-03 22:39:28 +01:00
Takumi Shotoku
4e097556d3
[v6.1.0.rc1] Fix regression for select tag helper with array ()
* Fix regression for select tag helper with array

v6.1.0.rc1 does not generate DOM with the selected attribute
when the object's method returns an array.
This is because it has been changed by  to always convert
to a string.

This commit fixes the issue.

## Steps to reproduce

```ruby
# frozen_string_literal: true

require "bundler/inline"

gemfile(true) do
  source "https://rubygems.org"

  git_source(:github) { |repo| "https://github.com/#{repo}.git" }

  gem "rails", ENV["RAILS_VERSION"]
end

require "action_view"
require "minitest/autorun"

class BugTest < ActionView::TestCase
  Post = Struct.new("Post", :tags)

  def test_stuff
    @post = Post.new
    @post.tags = ["foo", "bar"]
    expected = <<~DOM.strip
      <select name="post[tags]" id="post_tags"><option selected="selected" value="foo">foo</option>
      <option selected="selected" value="bar">bar</option>
      <option value="buz">buz</option></select>
    DOM

    assert_dom_equal(expected, select("post", "tags", %W(foo bar buz), { multiple: true }))
  end
end
```

The test succeeds on v6.0.3.4, but the test fails on v6.1.0.rc1.

* Update actionview/lib/action_view/helpers/tags/select.rb

[Takumi Shotoku + Rafael Mendonça França]
2020-11-03 13:27:51 -05:00
Rafael Mendonça França
8389f9902c
Preparing for 6.1.0.rc1 release 2020-11-02 21:12:47 +00:00
Sean Doyle
99ae95fda1 ARIA attributes: treat empty Hash and Array as nil
As a follow-up to [][], ensure that empty Hash and
Array arguments are treated as `nil`.

For example, when conditionally rendering an [aria-describedby][]
attribute to associate an input with a related validation error, treat
an empty Array as `nil`, an omit the attribute entirely:

```html+erb
<% post = Post.new %>

<%= form_with model: post do |form| %>
  <%= form.text_field :title, aria: { describedby: { post_title_error: post.errors[:title].any? } } %>
  <%= tag.span(post.errors[:title].to_sentence, id: :post_title_error) if post.errors[:title].any? %>
<% end %>
```

In this example, when there are no errors, the desired outcome is for
the `<input type="text" name="post[title]">` element to _omit_ the
`[aria-describedby="post_title_error"]` attribute, and to only include
it when there are errors on the `title` attribute.

Without this change, the desired outcome can be achieved with a
combination of a `#token_list` and `#presence` call:

```diff
<% post = Post.new %>

<%= form_with model: post do |form| %>
-  <%= form.text_field :title, aria: { describedby: {post_title_error: post.errors[:title].any?} }
+  <%= form.text_field :title, aria: { describedby: token_list(post_title_error: post.errors[:title].any?).presence } %>
  <%= tag.span(post.errors[:title].to_sentence, id: :post_title_error) if post.errors[:title].any? %>
<% end %>
```

[]: https://github.com/rails/rails/pull/40479
[aria-describedby]: https://www.w3.org/WAI/WCAG21/Techniques/aria/ARIA21#example-2-identifying-errors-in-data-format
2020-10-31 16:51:18 -04:00
Sean Doyle
a086418283 Yield translation to FormBuilder#button block
When translating a `<button>` element's contents, it is tedious  to make
the translation text available to a block scope.

For instance, when rendering a `<button type="submit">` with an SVG
element as its child, passing translated label text to that SVG
element's [`<title>`][svg-title] element requires an extra call to
`I18n.translate`.

Prior to this commit, doing so would require a double lookup of the
translation key:

```erb
<%# one time here, implicitly %>
<%= form.button do %>
  <svg>
    <title>
      <!-- one time here, explicitly -->
      <%= translate("helpers.submit.post.create") %>
    </title>
    <!-- ... -->
  </svg>
<% end %>
```

This commit modifies the `ActionView::Helpers::FormBuilder#button` to
check for invocations that are passed a block, and conditionally yield
the contents of `submit_default_value` as the argument.

The new view code might look something like this:

```erb
<%= form.button do |text| %>
  <svg>
    <title><%= text %></title>
    <!-- ... -->
  </svg>
<% end %>
```

Callers of the helper are still free to omit the block parameter.

[svg-title]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title
2020-10-30 16:30:56 -04:00
Sean Doyle
d38c214b75 Yield Tags::Label::LabelBuilder#translations
When translating a `<label>` element's contents, it is difficult (or
"possible", yet undocumented) to make the translation text available to
a block scope.

For instance, when rendering a `rich_text_area`, passing the
`aria-label` attribute might be important.

Prior to this commit, doing so would require a double lookup of the
translation key:

```erb
<%# one time here, implicitly %>
<%= form.label(:content) do %>
  <%= form.rich_text_area(
    :content,
    # one time here, explicitly
    "aria-label" => translate("helpers.label.post.content"),
  ) %>
<% end %>
```

The current implementation of the `#label` helper method already yields
an instance of `ActionView::Helpers::Tags::Label::LabelBuilder`, but
that class is undocumented. Instance of that class respond to
`#translation` calls, which will return the translated text content.

By aliasing `#translation` to `#to_s`, we're able to expose that value
without the burden of exposing an additional class to the public API.
Instead, view-level interpolation (either `<%= %>`, `#{ }`, or direct
calls to [`capture`][capture] will coerce the value to a String, and
implicitly invoke `#translation`.

The new view code might look something like this:

```erb
<%= form.label(:content) do |label| %>
  <%= form.rich_text_area(:content, "aria-label" => label) %>
<% end %>
```

Callers of the helper are still free to omit the block parameter.

[capture]: https://api.rubyonrails.org/classes/ActionView/Helpers/CaptureHelper.html#method-i-capture
2020-10-30 15:59:56 -04:00
Sean Doyle
67409e03a4 Alias TagHelper#class_names to #token_list
Rename the new `TagHelper#class_names` method to `TagHelper#token_list`,
and make the original available as an alias.

Inspired by a discussion on [][]

Once rendered by a browser, [an element's `class` attribute is
represented as a `DOMTokenList`][mdn-domtokenlist]. It's a
space-delimited list with unique elements.

Outside of the HTML `[class]` attribute, there are other attributes that
are represented as space-delimited lists. A non-exhaustive list
includes:

* [aria-labelledby][mdn-aria-labelledby]
* [aria-describedby][mdn-aria-describedby]
* [data-controller][data-controller] (in StimulusJS applications)
* [data-action][data-action] (in StimulusJS applications)

To support these attributes, ensure the collection of values from the
`class_names` helper is a unique Set.

[]: https://github.com/rails/rails/pull/40121#issuecomment-683366103
[class_names]: https://edgeapi.rubyonrails.org/classes/ActionView/Helpers/TagHelper.html#method-i-class_names
[mdn-aria-labelledby]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-labelledby_attribute#Value
[mdn-aria-describedby]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-describedby_attribute#Value
[data-action]: https://stimulusjs.org/reference/actions
[data-controller]: https://stimulusjs.org/reference/controllers
2020-10-30 13:20:13 -04:00
Sean Doyle
8b19d66fc6 Serialize aria- namespaced list attributes
Summary
===

Prior to this commit, calls passing `aria: { labelledby: [...] }`
serialized the `aria-labelledby` Array value as JSON.

This commit introduces special case logic to serialize `aria-` prefixed
`TrueClass`, `FalseClass`, `Hash`, and `Array` values more
appropriately.

An element's [`aria-labelledby` attribute][aria-labelledby] and
[`aria-describedby` attribute][aria-describedby] can accept a
space-delimited list of identifier values (much like the [`class`
attribute][class] accepts a space delimited [`DOMTokenList`
value][DOMTokenList]).

Similarly, there are [no boolean `aria-` attributes][aria-attributes]
(only `true`, `false`, or undefined), so this commit serializes `true`
to `"true"` and `false` to `"false"`.

Testing
---

This change moves an assertion _outside_ of a loop over `["aria",
:aria]`. Prior to this change, the second assertion within the loop
wasn't utilizing the iterated value as a Hash key. That is to say:
`aria:` (where an `aria` local variable is declared) is not equivalent
an equivalent syntax to `aria =>`.

Since the migration to `**options` in response to Ruby 2.7 deprecations,
invoking `tag.a("aria" => {...})` incorrectly coerces the `"aria" =>
{...}` has to be the `TagBuilder#a` method `content = nil` ordered
argument, instead of its `options` keyword arguments. This commit does
not modify that behavior, but it _does_ move the assertion outside the
block so that it isn't run unnecessarily.

[aria-labelledby]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-labelledby_attribute
[aria-describedby]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-describedby_attribute
[aria-attributes]: https://www.w3.org/TR/wai-aria-1.1/#propcharacteristic_value
[class]: https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/class
[DOMTokenList]: https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList
[class_names]: https://edgeapi.rubyonrails.org/classes/ActionView/Helpers/TagHelper.html#method-i-class_names
2020-10-29 21:55:33 -04:00
Jonathan Hefner
614e813161
Disentangle Action Text from ApplicationController
This commit allows Action Text to be used without having an
ApplicationController defined.  In doing so, it also fixes Action Text
attachments to render the correct URL host in mailers.

It also avoids allocating an ActionController::Renderer per request.

Fixes .
Fixes .
Fixes .
Closes .

Co-authored-by: Jeremy Daer <jeremydaer@gmail.com>
2020-10-30 01:01:42 +00:00
Rafael Mendonça França
6583895ebe
Remove deprecated escape_whitelist from ActionView::Template::Handlers::ERB 2020-10-30 00:25:30 +00:00
Rafael Mendonça França
dafa49bb4c
Remove deprecated find_all_anywhere from ActionView::Resolver 2020-10-30 00:25:29 +00:00
Rafael Mendonça França
db5a2dfe3e
Remove deprecated formats from ActionView::Template::HTML 2020-10-30 00:25:29 +00:00
Rafael Mendonça França
6124294684
Remove deprecated formats from ActionView::Template::RawFile 2020-10-30 00:25:28 +00:00
Rafael Mendonça França
217eb5dc4a
Remove deprecated formats from ActionView::Template::Text 2020-10-30 00:25:27 +00:00
Rafael Mendonça França
71904857d4
Remove deprecated find_file from ActionView::PathSet 2020-10-30 00:25:27 +00:00