Before this change while inspect was respecting that option, attribute_for_inspect
was not.
I also changed inspect to use attribute_for_inspect so we make sure the behavior
is consistent in the two places and simplified the implementation.
Fixes#40725.
This links the first mention of each method to its API documentation,
similar to a Wikipedia article.
This also modifies the text in a few places to ensure that methods are
explicitly mentioned and linked.
`form_with` would generate a remote form by default.
This confused users because they were forced to handle remote requests.
All new 6.1 applications will generate non-remote forms by default.
When upgrading a 6.0 application you can enable remote forms by default by
setting `config.action_view.form_with_generates_remote_forms` to `true`.
This change allows for applications to optionally run a `default_scope`
on `update` and `delete` queries. Default scopes already ran on select
and insert queries.
Applications can now run a set default scope on all queries for a model
by setting a `all_queries` option:
```ruby
class Article < ApplicationRecord
default_scope -> { where(blog_id: 1) }, all_queries: true
end
```
Using the default scope in this way is useful for applications that need
to query by more than the primary key by default. An example of this
would be in an application using a sharding strategy like Vitess like.
For Rails sharding, we route connections first and then query the
database. However, Vitess and other solutions use a parameter in the
query to figure out how to route the queries. By extending
`default_scope` to apply to all queries we can allow applications to
optionally apply additional constraints to all queries. Note that this
only works with `where` queries as it does not make sense to select a
record by primary key with an order. With this change we're allowing
apps to select with a primary key and an additional key.
To make this change dynamic for routing queries in a tenant sharding
strategy applications can use the `Current` API or parameters in a
request to route queries:
```ruby
class Article < ApplicationRecord
default_scope -> { where(blog_id: Current.blog.id) }, all_queries: true
end
```
In order to achieve this I created a new object when default scopes are
created. This allows us to store both the scope itself and whether we
should run this on all queries. I chose not to implement an `on:` option
that takes an array of actions because there is no simple or clear way
to turn off the default scope for create/select. It also doesn't really
make sense to only have a default scope for delete queries. The decision
to use `all_queries` here allows for the implementation to be more
flexible than it was without creating a mess in an application.
`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
Follow-up to 75c309c7ad.
As a result of these changes, attributes can have their type and default
value configured separately. Similar behavior was implemented in #39380,
but only for attributes that derive (and do not override) their type
from the database.
This links the first mention of each method to its API documentation,
similar to a Wikipedia article.
This also modifies the text in a few places to ensure that methods are
explicitly mentioned and linked.
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>
It's a useful note, but it's not at the right level of abstraction. This entire pack is about loading high level frameworks. Not adding individual functions.
We should find a way to present this information in either a guide or another type of helper that's then included here.
Since #40222, Action Text HTML is rendered in the context of the current
request. This causes the Action Text template format to default to the
request format, which prevents the template from being resolved when the
request format is not `:html` (e.g. `:json`). Therefore, override the
template format to always be `:html`.
Fixes#40695.
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