Skip to content

Commit 9e49ab2

Browse files
authored
Merge pull request rails#53135 from byroot/clarify-strict-locals-guide
Clarify the use case for Strict Locals
2 parents 5d5bf63 + 619c3a9 commit 9e49ab2

File tree

1 file changed

+39
-14
lines changed

1 file changed

+39
-14
lines changed

guides/source/action_view_overview.md

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -599,22 +599,48 @@ enables compact partial-local default variable assignments:
599599
<% end %>
600600
```
601601

602-
INFO: By default, partials will accept any `locals` as keyword arguments. To
603-
define what `locals` a partial accepts, use a `locals:` magic comment. To learn
604-
more, read about [Strict Locals](#strict-locals).
605-
606602
[local_assigns]:
607603
https://api.rubyonrails.org/classes/ActionView/Template.html#method-i-local_assigns
608604

609605
### Strict Locals
610606

611-
Action View partials will accept any number of `locals` as keyword arguments.
607+
Action View partials are compiled into regular Ruby methods under the hood.
608+
Because it is impossible in Ruby to dynamically create local variables, every single combination of `locals` passed to
609+
a partial requires compiling another version:
610+
611+
```html+erb
612+
<%# app/views/articles/show.html.erb %>
613+
<%= render partial: "article", layout: "box", locals: { article: @article } %>
614+
<%= render partial: "article", layout: "box", locals: { article: @article, theme: "dark" } %>
615+
```
616+
617+
The above snippet will cause the partial to be compiled twice, taking more time and using more memory.
618+
619+
```ruby
620+
def _render_template_2323231_article_show(buffer, local_assigns, article:)
621+
# ...
622+
end
623+
624+
def _render_template_3243454_article_show(buffer, local_assigns, article:, theme:)
625+
# ...
626+
end
627+
```
628+
629+
When the number of combinations is small, it's not really a problem, but if it's large it can waste
630+
a sizeable amount of memory and take a long time to compile. To counter act this you can use
631+
strict locals to define the compiled partial signature, and ensure only a single version of the partial is compiled:
632+
633+
```html+erb
634+
<%# locals: (article:, theme: "light") -%>
635+
...
636+
```
637+
612638
You can enforce how many and which `locals` a template accepts, set default
613-
values, and more with a `locals:` magic comment.
639+
values, and more with a `locals:` signature, using the same syntax as Ruby method signatures.
614640

615-
Here are some examples of the `locals:` magic comment:
641+
Here are some examples of the `locals:` signature:
616642

617-
```erb
643+
```html+erb
618644
<%# app/views/messages/_message.html.erb %>
619645
620646
<%# locals: (message:) -%>
@@ -640,15 +666,14 @@ If a default value is set then it can be used if `message` is not passed in
640666
```
641667

642668
Rendering the partial without a `:message` local variable uses the default value
643-
set in the `locals:` magic comment:
669+
set in the `locals:` signature:
644670

645671
```ruby
646672
render "messages/message"
647673
# => "Hello, world!"
648674
```
649675

650-
Rendering the partial with local variables not specified in the `local:` magic
651-
comment will also raise an exception:
676+
Rendering the partial with local variables not specified in the `local:` signature will also raise an exception:
652677

653678
```ruby
654679
render "messages/message", unknown_local: "will raise"
@@ -682,15 +707,15 @@ render "messages/message", unknown_local: "will raise"
682707
# => ActionView::Template::Error: no locals accepted for app/views/messages/_message.html.erb
683708
```
684709

685-
Action View will process the `locals:` magic comment in any templating engine
686-
that supports `#`-prefixed comments, and will read the magic comment from any
710+
Action View will process the `locals:` signature in any templating engine
711+
that supports `#`-prefixed comments, and will read the signature from any
687712
line in the partial.
688713

689714
CAUTION: Only keyword arguments are supported. Defining positional or block
690715
arguments will raise an Action View Error at render-time.
691716

692717
The `local_assigns` method does not contain default values specified in the
693-
`local:` magic comment. To access a local variable with a default value that
718+
`local:` signature. To access a local variable with a default value that
694719
is named the same as a reserved Ruby keyword, like `class` or `if`, the values
695720
can be accessed through `binding.local_variable_get`:
696721

0 commit comments

Comments
 (0)