Commit Graph

2245 Commits

Author SHA1 Message Date
Aaron Patterson 0915a3eed8
Merge pull request #49858 from skipkayhil/hm-dont-assign-internal-variables
Prevent assigning internal ivars to AV::Base
2023-12-11 09:06:05 -08:00
Jean Boussier be258503ac Module#delegate takes a new private `as` parameter
This is a continuation of https://github.com/rails/rails/pull/46875

The behavior of looking up the class method when `to: :class` is passed
is a bit error prone because it silently degrades.

By passing the expected owner of the delegated method, we can be more
strict, and also generate a delegator in a module rather than having
to do it at inclusion time.

I made this argument private API because we want it in Rails, but
I'm worried it might be a bit too sharp for public API. I can
be convinced otherwise though.
2023-12-08 15:09:59 +01:00
Akhil G Krishnan 204d86b1a2 Improve documentation for highlight text helper
Update actionview/lib/action_view/helpers/text_helper.rb

Co-authored-by: Jonathan Hefner <jonathan@hefner.pro>

Update actionview/lib/action_view/helpers/text_helper.rb

Co-authored-by: Jonathan Hefner <jonathan@hefner.pro>

Update actionview/lib/action_view/helpers/text_helper.rb

Co-authored-by: Jonathan Hefner <jonathan@hefner.pro>
2023-12-04 01:03:19 +05:30
Sean Doyle 9de8f1a26a Action View Docs: `field_id` and `field_name` examples [ci skip]
Several code samples for `field_id` and `field_name` cite the use of
[text_field_tag][]-style helper. That usage is incorrect. The helper
interface that `field_id` and `field_name` mimic is the
[text_field][]-style helper, without the `_tag` suffix.

[text_field_tag]: https://edgeapi.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html#method-i-text_field_tag
[text_field]: https://edgeapi.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-text_field
2023-12-02 09:04:12 -05:00
Jean Boussier 90daef6928
Merge pull request #50241 from seanpdoyle/fieldset-tag-alias
Alias `field_set_tag` helper to `fieldset_tag`
2023-12-02 10:23:24 +01:00
Sean Doyle 0803405fdb Batch define `FormBuilder` methods with `CodeGenerator`
Define the `ActionView::Helpers::FormBuilder` methods that wrap the
`@template` instance methods inside an
`ActiveSupport::CodeGenerator.batch` call so that the underlying `class`
extensions aren't invoked more than once.
2023-12-02 10:08:24 +01:00
Sean Doyle c5ae44d659 Alias `field_set_tag` helper to `fieldset_tag`
The [field_set_tag][] renders a `<fieldset>` element. At times, the
desire to render a `fieldset` results in calling `fieldset_tag`, only to
be surprised by a `NoMethodError`.

Originally, the method's name was `fieldset_tag` helper (defined in
[0e6c8e5][] in 2007), but was renamed in [73c7083][] (3 days later).

This commit aliases `field_set_tag` to `fieldset_tag` so that both are
available.

Additionally, defines the method so that it utilizes the [content_tag][]
so that it isn't responsible for manually managing the closing
(`</fieldset>`) of the opening `<fieldset>` tag.

[field_set_tag]: https://edgeapi.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html#method-i-field_set_tag
[0e6c8e5]: 0e6c8e5f6c
[73c7083]: 73c7083651
[content_tag]: https://edgeapi.rubyonrails.org/classes/ActionView/Helpers/TagHelper.html#method-i-content_tag
2023-12-02 01:09:42 -05:00
Eileen M. Uchitelle d6197c5efc
Merge pull request #50159 from skipkayhil/hm-deprecate-void-content
Deprecate content for void elements in TagBuilder
2023-12-01 09:34:30 -05:00
Jonathan Hefner 52affa8357 Fix example output for truncate helper [ci-skip]
The previous output was incorrect for the default truncation length, and
it included unescaped quotes.
2023-11-30 11:19:37 -06:00
Akhil G Krishnan c5add29025 Improve documentation for truncate text helper
Update actionview/lib/action_view/helpers/text_helper.rb

Co-authored-by: Jonathan Hefner <jonathan@hefner.pro>

Update actionview/lib/action_view/helpers/text_helper.rb

Co-authored-by: Jonathan Hefner <jonathan@hefner.pro>

Update actionview/lib/action_view/helpers/text_helper.rb

Co-authored-by: Jonathan Hefner <jonathan@hefner.pro>

Update actionview/lib/action_view/helpers/text_helper.rb

Co-authored-by: Jonathan Hefner <jonathan@hefner.pro>

Update actionview/lib/action_view/helpers/text_helper.rb

Co-authored-by: Jonathan Hefner <jonathan@hefner.pro>

Update actionview/lib/action_view/helpers/text_helper.rb

Co-authored-by: Jonathan Hefner <jonathan@hefner.pro>
2023-11-30 10:51:11 +05:30
Hartley McGuire c1f3d6851e
Remove unused DeprecatedConstantAccessor include
deprecate_constant removed in 23344d4b8c
2023-11-26 12:38:21 -05:00
Akhil G Krishnan 4c9d56a5c4 Improve documentation for excerpt text helper
Co-authored-by: Jonathan Hefner <jonathan@hefner.pro>
2023-11-25 11:16:28 +05:30
Jonathan Hefner df2961b3d7 Put Ruby code in ERB tags [ci-skip]
This allows the code to be properly syntax-highlighted.
2023-11-24 17:57:17 -06:00
Jonathan Hefner ed694bfe0a Remove unused variable in code example [ci-skip] 2023-11-24 17:52:33 -06:00
Jonathan Hefner 4bfa69a785 Revise TextHelper#concat code example [ci-skip]
This simplifies the code example, and avoids putting `%>` _inside_ an
ERB tag, which confuses the syntax highlighter.
2023-11-24 17:19:47 -06:00
Jonathan Hefner ca5c27ed63 Format inline code [ci-skip] 2023-11-24 16:47:20 -06:00
Jonathan Hefner 1d604a459b Quote example output strings [ci-skip]
This portrays the return values more accurately and, in some cases,
fixes syntax highlighting when using the upcoming version of SDoc
(thanks to its heuristic for detecting Ruby code vs HTML code).
2023-11-24 16:22:57 -06:00
Jonathan Hefner dc53bb9c27 Fix prose indentation [ci-skip]
Prior to this commit, the prose was formatted as a code example.
2023-11-24 16:13:03 -06:00
Hartley McGuire 343897980c
Deprecate content for void elements in TagBuilder
According to the [HTML5 Spec][1]

> Void elements can't have any contents (since there's no end tag, no
> content can be put between the start tag and the end tag).

Up to this point, the only special handling of void elements has been to
use ">" to close them instead of "/>" (which is optional but valid
according to the spec)

> Then, if the element is one of the void elements, ... , then there may
> be a single U+002F SOLIDUS character (/), ... . On void elements, it
> does not mark the start tag as self-closing but instead is unnecessary
> and has no effect of any kind.

This commit deprecates the ability to pass content (either through the
positional "content" parameter or a block) to a void element since it is
not valid according to the Spec. This has the benefit of both
encouraging more correct HTML generation, and also simplifying the
method definition of void elements once the deprecation has been
removed.

This commit additionally tweaks the signature of "void_tag_string"
slightly with two changes. The first change is renaming it to be
"self_closing_tag_string". This is more accurate than "void_tag_string"
because the definition of "void element" is more specific and has more
requirements than "self closing element". For example, tags in the SVG
namespace _can_ be self closing but the "/" at the end of the start tag
is _not_ optional because they are not void elements. The second change
to this method is swapping from a boolean "self_closing" parameter to a
string "tag_suffix" parameter. This enables the void element method
definition to specialize the tag_suffix (to just ">") without either
void elements or self closing elements having to pay the runtime cost of
the self_closing conditional since we know at method definition time
which suffix each type of tag should use.

[1]: https://html.spec.whatwg.org/multipage/syntax.html#void-elements
2023-11-24 11:42:57 -05:00
Hartley McGuire 28c4f6b598
Fix preposition in fields_for doc
Followup to 2a5e9bc85b
2023-11-22 09:07:17 -05:00
Jonathan Hefner 2191f20706 Fix word_wrap with empty string
Follow-up to #45948.

This fixes `word_wrap` to return an empty string instead of `nil` when
given an empty string.

Fixes #50067.
2023-11-15 16:22:02 -06:00
Jean Boussier 427898293d ActionView::Template fix computation of strict locals
Fix: https://github.com/rails/rails/pull/49782

There was a bug in how we computed the list of required keys which
wasn't caught by the test.
2023-11-14 13:14:59 +01:00
Collin Jilbert 2a5e9bc85b fix preposition in ActionView::Helpers::FormHelper comments 2023-11-09 10:35:34 -06:00
Garen Torikian 94de154a23 Update documentation in asset_tag_helper.rb
Just a wee bit of visualization changes to make it more explicitly clear what is being passed (a quoted number)

Co-authored-by: Jonathan Hefner <jonathan@hefner.pro>
2023-11-07 16:42:59 -06:00
Jonathan Hefner 916c419dad Fix formatting of AV::TestCase.register_parser doc [ci-skip]
This fixes a few issues with the formatting of the API documentation for
`ActionView::TestCase::Behavior::ClassMethods#register_parser`:

* Use `h4` headings instead of `h3` headings.  SDoc renders method
  signatures as `h3` headings, so subheadings such as "Examples" should
  use `h4`.

* Replace "Arguments" heading with "Parameters".  "Parameters" are
  elements of function's signature, whereas "arguments" are elements of
  a function call.  The API documentation for other methods follows this
  convention.

* Format parameters as term list.

* Fix indentation of pre-registered parser lists to render them as lists
  instead of as code.

* Miscellaneous rewording, reorganization, and additional monospace
  formatting.
2023-11-04 22:55:13 -05:00
Hartley McGuire 24213d6954
Prevent assigning internal ivars to AV::Base
Previously, both the `@rendered_format` and
`@marked_for_same_origin_verification` instance variables would be
assigned to instances of `ActionView::Base`, making them accessible in
view templates. However, these instance variables are really internal to
the controller and result in extra string allocations because the `@`
gets stripped and readded when going through the assignment.

This commit prefixes the variables with an underscore to help indicate
that they are internal, and then adds them to the list of
`_protected_ivars` to prevent assigning them when rendering templates.

Co-authored-by: Jean Boussier <jean.boussier@gmail.com>
Co-authored-by: Jonathan Hefner <jonathan@hefner.pro>
2023-11-03 20:52:47 -04:00
Jonathan Hefner f15cf4b093 Format inline code [ci-skip] 2023-10-26 17:37:32 -05:00
Jean Boussier 110206a74b Ignore implicit locals if not declared by templates with strict locals
Fix: https://github.com/rails/rails/pull/49780
Fix: https://github.com/rails/rails/issues/49761

`CollectionRenderer` implictly inject `<name>_counter` and `<name>_iteration`
locals, but in the overwhelming majority of cases they aren't used.

So when the rendered template has strict locals we shouldn't require
these to be declared, and if they aren't we should simply not pass them.

Co-Authored-By: HolyWalley <yakau@hey.com>
2023-10-25 17:45:59 +02:00
Wojciech Wnętrzak e6a096968b
Fix code example in the field_name method 2023-10-18 15:20:57 +02:00
Jean Boussier 79a242dc54 Fix `capture` view helper for HAML and Slim
Ref: https://github.com/rails/rails/pull/47194#issuecomment-1760334146

They both give the buffer as return value of the capture block
which confuses the `capture` helper.

Ideally we wouldn't have to check for that, but it's
an acceptable tradeoff for backward compatibility.
2023-10-13 08:27:09 +02:00
fatkodima b8829cabec Enable `Style/RedundantDoubleSplatHashBraces` rubocop cop 2023-10-11 14:55:00 +03:00
Akira Matsuda 8104683c65
"NoMethodError: undefined method `pluralize' for an instance of Symbol"
https://buildkite.com/rails/rails/builds/100525#018b10a0-9ed9-4c7b-b6d2-028ed05a0a04
2023-10-09 12:28:14 +09:00
Sean Doyle 67bb1b64b7 Define `TagBuilder` methods for void Elements
The `ActionView::Helpers::TagHelper::TagBuilder` class renders HTML
elements based on the methods invoked on it. For example, `tag.input`
will render an `<input>` element, while `tag.turbo_frame` will render a
`<turbo-frame>` element.

The magic of the class is rooted in its definition of `#method_missing`.

The current implementation bakes-in special treatment of void HTML
elements (for example: `<input>`) and self-closing SVG elements (for
example: `<use />`). Despite its ahead-of-time knowledge of these
element names, calls to corresponding methods `tag.input` and `tag.use`
still rely on `#method_missing`.

This has performance implications.

This commit defines a new `TagBuilder.define_void_element` class method
to dynamically define methods for each known element. Then, the class
invokes the method for each element name in `HTML_VOID_ELEMENTS` and
`SVG_SELF_CLOSING_ELEMENTS`.

Calls to `.define_void_element` and `.define_self_closing_element` makr
`HTML_VOID_ELEMENTS` and `SVG_SELF_CLOSING_ELEMENTS` unnecessary, so
this commit removes those constant definitions.

Additionally, this call removes calls to
`TagHelper.ensure_valid_html5_tag_name` from the `TagBuilder` defined
element methods, since they're known ahead of time to be valid HTML.
Instead, only call `ensure_valid_html5_tag_name` from within the
`method_missing` calls, since those are determined at runtime and are
uncontrolled.

By cutting out the reliance on method missing, calls to `TagBuilder`
methods (like `tag.input`) become comparable to calls to the `tag` view
helper with positional arguments (like `tag(:input)`).

```
❯ ruby bench.rb
Warming up --------------------------------------
                 tag    73.438k i/100ms
         tag_builder    79.910k i/100ms
Calculating -------------------------------------
                 tag    732.467k (± 0.9%) i/s -      3.672M in   5.013504s
         tag_builder    810.981k (± 0.8%) i/s -      4.075M in   5.025632s

Comparison:
         tag_builder:   810981.5 i/s
                 tag:   732467.4 i/s - 1.11x  (± 0.00) slower
```

The results were from the following benchmark rendering void (`<input>`)
elements:

```ruby
 # frozen_string_literal: true

require "bundler/setup"

require "action_view"
require "minitest/autorun"
require "benchmark/ips"

class Foo
  include ActionView::Helpers
end

helpers = Foo.new

Benchmark.ips do |x|
  x.report("tag") { helpers.tag("input", value: "foo") }
  x.report("tag_builder") { helpers.tag.input(value: "foo") }
  x.compare!
end
```

Similar to `tag.input` (a void HTML element), calls to `tag.div` are
become somewhat comparable to `tag("div")`:

```
❯ ruby bench.rb
Warming up --------------------------------------
         content_tag    59.548k i/100ms
         tag_builder    51.215k i/100ms
Calculating -------------------------------------
         content_tag    595.067k (± 0.5%) i/s -      2.977M in   5.003570s
         tag_builder    505.553k (± 2.2%) i/s -      2.561M in   5.067704s

Comparison:
         content_tag:   595067.5 i/s
         tag_builder:   505552.6 i/s - 1.18x  (± 0.00) slower
```

The following benchmarks were collected to compare `tag("turbo-frame")`
(an unknown custom HTML element) and `tag.turbo_frame`:

```
❯ ruby bench.rb
Warming up --------------------------------------
         content_tag    56.152k i/100ms
         tag_builder    49.207k i/100ms
Calculating -------------------------------------
         content_tag    561.134k (± 0.5%) i/s -      2.808M in   5.003567s
         tag_builder    491.178k (± 0.3%) i/s -      2.460M in   5.009140s

Comparison:
         content_tag:   561133.8 i/s
         tag_builder:   491177.7 i/s - 1.14x  (± 0.00) slower
```
2023-10-05 08:51:52 -04:00
Kevin Newton d743a2b10f
Use Prism for parsing renders when available
Instead of ripper
2023-09-29 20:57:54 -04:00
Jean Boussier dfd086edf3 Fix RenderCallExtractor to be compatible with Ruby 3.3
Fix: https://github.com/rails/rails/issues/49128
Ref: https://github.com/ruby/ruby/commit/45cd011d73

We need to unwrap some nodes.
2023-09-28 14:35:01 +02:00
Akhil G Krishnan bb626ffca8 HTML tag validation added for tags
Added validation for HTML tag names in the `tag` and `content_tag` helper method. The `tag` and
`content_tag` method now checks that the provided tag name adheres to the HTML specification. If
an invalid HTML tag name is provided, the method raises an `ArgumentError` with an appropriate error
message.

Examples:

```ruby
content_tag("12p") # Starting with a number

content_tag("") # Empty tag name

tag("div/") # Contains a solidus

tag("image file") # Contains a space
```
2023-09-27 18:11:01 +05:30
Rafael Mendonça França fb6c6007d0
Development of Rails 7.2 starts now
🎉
2023-09-27 03:59:11 +00:00
Rafael Mendonça França e5386cb402
Preparing for 7.1.0.rc1 release 2023-09-27 03:08:31 +00:00
Sean Doyle 7badc42723
Introduce `ActionView::TestCase.register_parser`
Register a callable to decode rendered content for a given MIME type

Each registered decoder will also define a `#rendered.$MIME` helper
method, where `$MIME` corresponds to the value of the `mime` argument.

=== Arguments

`mime` - Symbol the MIME Type name for the rendered content
`callable` - Callable to decode the String. Accepts the String
                    value as its only argument
`block` - Block serves as the decoder when the
                 `callable` is omitted

By default, ActionView::TestCase defines a decoder for:

* :html - returns an instance of Nokogiri::XML::Node
* :json - returns an instance of ActiveSupport::HashWithIndifferentAccess

Each pre-registered decoder also defines a corresponding helper:

* :html - defines `rendered.html`
* :json - defines `rendered.json`

=== Examples

To parse the rendered content into RSS, register a call to `RSS::Parser.parse`:

```ruby
register_decoder :rss, -> rendered { RSS::Parser.parse(rendered) }

test "renders RSS" do
  article = Article.create!(title: "Hello, world")

  render formats: :rss, partial: article

  assert_equal "Hello, world", rendered.rss.items.last.title
end
```

To parse the rendered content into a Capybara::Simple::Node,
re-register an `:html` decoder with a call to
`Capybara.string`:

```ruby
register_decoder :html, -> rendered { Capybara.string(rendered) }

test "renders HTML" do
  article = Article.create!(title: "Hello, world")

  render partial: article

  rendered.html.assert_css "h1", text: "Hello, world"
end
```
2023-09-27 02:03:23 +00:00
Bhanu Bhakta Sigdel 72b3fe9f09 Update doc for `include_hidden` form form file_field.
Update `include_hidden: false` to `include_hidden: true`

Update the language to be more accurate.

Update actionview/lib/action_view/helpers/form_helper.rb

Co-authored-by: Hartley McGuire <skipkayhil@gmail.com>
2023-09-24 19:44:08 -06:00
Sean Doyle 8b77436dbc Add documentation for `locals:` and `local_assigns` [ci skip]
Expand the documentation for [local_assigns][] to mention potential
integrations with [Ruby 3.1's pattern matching
assignment][pattern-matching].

Expand the Action View Overview guides to describe calls to `render`
with `locals:` options, along with the existence of the `local_assigns`
method. Also outline potential integrations with Ruby 3.1's pattern
matching assignment.

[local_assigns]: https://api.rubyonrails.org/classes/ActionView/Template.html#method-i-local_assigns
[pattern-matching]: https://docs.ruby-lang.org/en/master/syntax/pattern_matching_rdoc.html
2023-09-18 08:31:03 -04:00
Sean Doyle 32faee0e52 Action View: docs use `application/` instead of `shared/`
Change mentions of `app/views/shared` in the guides to be
`app/views/application` instead. View partials rely on the same
[Template Inheritance][] as their template counterparts, so the guides
should encourage end-users to benefit from that inheritance.

> This makes `app/views/application/` a great place for your shared
> partials, which can then be rendered in your ERB as such:
>

```html+erb
<%# app/views/admin/products/index.html.erb %>
<%= render @products || "empty_list" %>

<%# app/views/application/_empty_list.html.erb %>
There are no items in this list <em>yet</em>.
```

To enforce that template resolution, this commit also replaces
references to `shared/` with `application/` in the Rails test suite.

[Template Inheritance]: https://guides.rubyonrails.org/layouts_and_rendering.html#template-inheritance
2023-09-15 12:06:22 -04:00
Sean Doyle a9148b45f3 Add "Testing View Partials" section to the Testing Guides
Motivation / Background
---

While the `ActionView::TestCase` class isn't marked with a `:nodoc:`
comment to indicate that it's internal to Rails, there isn't much
content in the guides that explains how to test view partials.

Libraries like
[view_component](https://github.com/ViewComponent/view_component/) have
[built-in support for
testing](https://viewcomponent.org/guide/testing.html), including
Capybara integration.

While `ActionView::TestCase` already integrates with
`rails-dom-testing`, that integration could be better documented.
Additionally, it wouldn't take much for consuming applications to mimic
the ViewComponent testing experience for their Action View Partials.

Details
---

First, link to the "Testing Rails Applications" page from the
`ActionView::TestCase` class documentation.

Next, add a "Testing View Partials" section to the guides that expands
upon the variety of tooling available to tests that inherit from
`ActionView::TestCase`. In that section, cover topics like:

* the `render` helper method
* the `rendered` helper attribute reader
* calls to `assert_select` with attribute placeholders
* the `document_root_element` helper method
* integration with Ruby's Pattern Matching
* opportunities to integrate with Capybara

Additional Information
---

Additionally, add test coverage that exercise the examples shared in the
new section, including:

* Calls to `assert_select` that utilize attribute placeholders
* Ruby 3.0's Pattern Matching
* Integration with Capybara
2023-09-13 09:44:44 -04:00
Rafael Mendonça França 699dfdb426
Preparing for 7.1.0.beta1 release 2023-09-13 00:36:01 +00:00
Akhil G Krishnan 1677e31240
Fix: simple_format with blank wrapper_tag option returns plain html tag.
By default `simple_format` method returns the text wrapped with `<p>`. But if we explicitly specify
the `wrapper_tag: nil` in the options, it returns the text wrapped with `<></>` tag.

Before:
```ruby
 simple_format("Hello World", {},  { wrapper_tag: nil })
 # <>Hello World</>
```

After:
```ruby
 simple_format("Hello World", {},  { wrapper_tag: nil })
 # <p>Hello World</p>
```

Co-authored-by: Junichi Ito <jit@sonicgarden.jp>
2023-09-05 10:09:40 +00:00
Gannon McGibbon 7ea19698b0 Fix form_for id generation for new CPK models
Adds tests for form_for use with composite primary key models. Fixes bug
related to new CPK model dom id generation.
2023-08-28 15:56:25 -05:00
Oscar Romero 9db860f1b4
Document the :ignore_date option on time_select (#49017)
* Document the :ignore_date option on time_select

* split documentation comment into two lines

Co-authored-by: Rafael Mendonça França <rafael@franca.dev>
2023-08-23 15:41:53 -04:00
Jean Boussier 40d761c3e1
Merge pull request #48987 from Austio/better-dom-id-error-on-nil
Adds a specific ArgumentError when passing nil to dom_id.
2023-08-22 17:19:45 +02:00
Austin Story 6245c0048a Adds a specific ArgumentError when passing nil to dom_id. Which can happen if you do something like pass a non-existent ivar dom_id(@something_non_existant)
Before this would raise: `NoMethodError: undefined method `to_key' for nil:NilClass`
After it raises `ArumentError: dom_id must be passed a record_or_class as the first parameter, you passed 'nil'`
2023-08-22 17:16:25 +02:00
julianfssen 6a798d079a Add docs for `data-turbo-method` and `data-turbo-confirm` for `link_to`
Rails 7 ships with Turbo enabled by default. Instead of using
`data-method` and `data-confirm`, Turbo now uses `data-turbo-method` and
`data-turbo-confirm` to perform a link visit with the specified HTTP
method and show confirmation dialog respective.

The deprecated legacy options are documented but the new options are
not.

This commit documents the `data-turbo-method` and `data-turbo-confirm`
for the `link_to` method.

The `button_to` documentation has also been updated to reference the
new `link_to` options.
2023-08-16 19:09:17 +08:00