Skip to content

Linter Rule: Require data-herb-into to name a keyed collection

Rule: herb-into-requires-collection

Description

Requires the data-herb-into attribute on a form to be a static value naming a keyed collection in the same template, an element carrying data-herb-name around a loop whose rows are keyed by a herb:key directive, a dynamic herb-key attribute, or a dynamic id.

Rationale

A form with data-herb-into is an optimistic send: the runtime intercepts the submit and inserts a row into the named collection before the server answers. The name resolves within the form's own region, so it has to exist in this template, and it has to be a keyed collection, since an optimistic row needs a key to be confirmed under. A name that resolves to nothing, to a value slot, or to an unkeyed loop sends nothing at runtime and reports herb-unknown-collection in debug mode. This rule says the same thing in the editor, before the page runs.

Examples

✅ Good

erb
<ul data-herb-name="messages">
  <% @messages.each do |message| %>
    <%# herb:key message.id %>
    <li><%= message.body %></li>
  <% end %>
</ul>

<form action="/messages" method="post" data-herb-into="messages">
  <input name="body" autocomplete="off">
  <button>Send</button>
</form>

🚫 Bad

erb
<ul data-herb-name="messages">
  <% @messages.each do |message| %>
    <%# herb:key message.id %>
    <li><%= message.body %></li>
  <% end %>
</ul>

<form action="/messages" method="post" data-herb-into="posts">
`data-herb-into="posts"` names nothing in this template. Name a keyed collection with `data-herb-name` on the element around the loop. Collections in this template: `messages`. (herb-into-requires-collection)
<input name="body" autocomplete="off"> <button>Send</button> </form>
erb
<p data-herb-name="summary"><%= @summary %></p>

<form action="/messages" method="post" data-herb-into="summary">
`data-herb-into="summary"` names a slot that is not a keyed collection. A send inserts an item, so name the element around a keyed loop. (herb-into-requires-collection)
<input name="body" autocomplete="off"> <button>Send</button> </form>

References

-

Released under the MIT License.