Skip to content

Commit

Permalink
Add ADR for the new feature
Browse files Browse the repository at this point in the history
  • Loading branch information
fsateler committed Sep 9, 2021
1 parent 77ccbac commit 6e86882
Showing 1 changed file with 79 additions and 0 deletions.
79 changes: 79 additions & 0 deletions adr/0003-multiple-templates-per-component.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# 1. Allow multiple templates

Date: 2021-08-30

## Status

Proposed.

## Context

As components become larger (for example, because you are implementing a whole page), it becomes
useful to be able to extract sections of the view to a different file. ActionView has
partials, and ViewComponent lacks a similar mechanism.

ActionView partials have the problem that their interface is not introspectable. Data
may be passed into the partial via ivars or locals, and it is impossible to know
which without actually opening up the file. Additionally, partials are globally
invocable, thus making it difficult to detect if a given partial is in use or not,
and who are its users.

## Considered Options

* Introduce component partials to components
* Keep components as-is

### Component partials

Introduce an API to have multiple ERB templates available within the component,
and make it possible to invoke them from the main view. This API should be as
explicit as possible, in particular it should explicitly list the arguments it
receives (if any). This allows a single method to be compiled, and invoked
directly, without having to dance around with `binding` as ActionView partials
do.

**Pros:**
* Better performance due to lack of GC pressure and object creation
* Reduces the number of components needed to express a more complex view.
* Extracted sections are not exposed outside the component.

**Cons:**
* Another concept for users of ViewComponent to learn and understand.
* Components are no longer the only way to encapsulate behavior.

### Keeping components as-is

**Pros:**
* The API remains simple and components are the only way to encapsulate behavior.
* Encourages creating reusable sub-components.

**Cons:**
* Extracting a component results in more GC and intermediate objects.
* Extracting a component may result in tightly coupled but split components.
* Creates new public components thus expanding component library API surface.

## Decision

We will allow having multiple templates in the sidecar asset. Each asset will be compiled to
it's own method `call_<template_name>`. In order to allow the compiled method to receive arguments,
the component must define them via a `template_arguments :template_name, :argument1, :argument2`.
This will create required keyword arguments to the `call_<template_name>` method.

## Consequences

This implementation has better performance characteristics over both an extracted component
and ActionView partials, because it avoids creating intermediate objects, and the overhead of
creating bindings and `instance_exec`.
Having explicit arguments makes the interface explicit.

TODO: The following are consequences of the current approach, but the approach might be extended
to avoid them:

The interface to render a sidecar partial would be a method call, and depart from the usual
`render(*)` interface used in ActionView.

The generated methods are only invokable via keyword arguments

The generated methods cannot have arguments with default values.

The generated methods are public, and thus could be invoked by a third party.

0 comments on commit 6e86882

Please sign in to comment.