Skip to content

Commit a04f004

Browse files
committed
Add ADR for the new feature
1 parent 77ccbac commit a04f004

File tree

1 file changed

+79
-0
lines changed

1 file changed

+79
-0
lines changed
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# 1. Allow multiple templates
2+
3+
Date: 2021-08-30
4+
5+
## Status
6+
7+
Proposed.
8+
9+
## Context
10+
11+
As components become larger (for example, because you are implementing a whole page), it becomes
12+
useful to be able to extract sections of the view to a different file. ActionView has
13+
partials, and ViewComponent lacks a similar mechanism.
14+
15+
ActionView partials have the problem that their interface is not introspectable. Data
16+
may be passed into the partial via ivars or locals, and it is impossible to know
17+
which without actually opening up the file. Additionally, partials are globally
18+
invocable, thus making it difficult to detect if a given partial is in use or not,
19+
and who are its users.
20+
21+
## Considered Options
22+
23+
* Introduce component partials to components
24+
* Keep components as-is
25+
26+
### Component partials
27+
28+
Introduce an API to have multiple ERB templates available within the component,
29+
and make it possible to invoke them from the main view. This API should be as
30+
explicit as possible, in particular it should explicitly list the arguments it
31+
receives (if any). This allows a single method to be compiled, and invoked
32+
directly, without having to dance around with `binding` as ActionView partials
33+
do.
34+
35+
**Pros:**
36+
* Better performance due to lack of GC pressure and object creation
37+
* Reduces the number of components needed to express a more complex view.
38+
* Extracted sections are not exposed outside the component, thus reducing component library API surface.
39+
40+
**Cons:**
41+
* Another concept for users of ViewComponent to learn and understand.
42+
* Components are no longer the only way to encapsulate behavior.
43+
44+
### Keeping components as-is
45+
46+
**Pros:**
47+
* The API remains simple and components are the only way to encapsulate behavior.
48+
* Encourages creating reusable sub-components.
49+
50+
**Cons:**
51+
* Extracting a component results in more GC and intermediate objects.
52+
* Extracting a component may result in tightly coupled but split components.
53+
* Creates new public components thus expanding component library API surface.
54+
55+
## Decision
56+
57+
We will allow having multiple templates in the sidecar asset. Each asset will be compiled to
58+
it's own method `call_<template_name>`. In order to allow the compiled method to receive arguments,
59+
the component must define them via a `template_arguments :template_name, :argument1, :argument2`.
60+
This will create required keyword arguments to the `call_<template_name>` method.
61+
62+
## Consequences
63+
64+
This implementation has better performance characteristics over both an extracted component
65+
and ActionView partials, because it avoids creating intermediate objects, and the overhead of
66+
creating bindings and `instance_exec`.
67+
Having explicit arguments makes the interface explicit.
68+
69+
TODO: The following are consequences of the current approach, but the approach might be extended
70+
to avoid them:
71+
72+
The interface to render a sidecar partial would be a method call, and depart from the usual
73+
`render(*)` interface used in ActionView.
74+
75+
The generated methods are only invokable via keyword arguments
76+
77+
The generated methods cannot have arguments with default values.
78+
79+
The generated methods are public, and thus could be invoked by a third party.

0 commit comments

Comments
 (0)