When to Use call, erb_template, or html.erb in Rails ViewComponents?

ViewComponent has multiple methods to render ERB (or Slim) and HTML. Initially, when ViewComponent was released, there were two options, a:

  • separate html.erb file, and;
  • call method.

But since v3.0 there is another strategy you can use: erb_template. It essentially works the same as the call method, but also allows ERB or plain HTML. The goal for both call and erb_template is to eliminate an extra file. Keeping your component to one file only. Tidy and neat!

The three different rendering strategies

Let’s go over how each one works and then I give some guidelines to help you choose.

erb.html

This is the default way where the template is defined in a separate .html.erb file located in the same directory as the component class. In this file you can write any ERB or HTML you need.

# app/components/example_component.html.erb
<h1>Hello, <%= @name %>!</h1>

call

The call method can be used to write the rendering logic directly in Ruby component file. It’s the option that can render HTML using Rails’ ActionView content_tag or tag helpers or any other Ruby code.

# app/components/example_component.rb
class ExampleComponent < BaseComponent
  def initialize(name:)
    @name = name
  end

  def call
    content_tag(:h1, "Hello, #{@name}")
  end
end

erb_template

You can view the erb_template strategy as a merge of the above two strategies. You can write the same HTML + ERB as with html.erb file.

# app/components/example_component.rb
class ExampleComponent < BaseComponent
  def initialize(name:)
    @name = name
  end

  erb_template <<~ERB
    <h1>Hello, <%= @name %>!</h1>
  ERB
end

See that weird-looking <<~ERB? In Ruby it is called a “squiggly heredoc” and it allows for writing multi-line strings with automatic indentation removal.

You can of course also use other templating engines, Slim for example. That would look like this:

  #  slim_template <<~SLIM
    <h1>Hello, <%= @name %>!</h1>
  SLIM
  #

Which strategy to use?

So which strategy to use when? Over the few years of writing ViewComponent and building a UI Components library with it, I’ve build up some best practices when to use which strategy.

I use this as a guideline (as always with guidelines, change when it makes sense based on the context).

  1. one line of content, eg. content_tag(:h1, "Hello, #{@name}") use call;
  2. between 2 and 11 lines; use erb_template;
  3. more than 12 lines; use html.erb.

Where do I get these numbers from? Besides number 1, pretty much out of thin air. The rationale is that anything beyond 10 lines makes the component file feel more cluttered. Tucking it away in another file helps here (if you can’t see it, it isn’t there!). The reality is that I nowadays (since the introduction of erb_template) mostly use that strategy.

Your mileage may vary. Maybe you choose a range between 2 and 19. Fine by me! Agree on a number between yourself/your team and use that as a guideline. But having a guideline give you something to reason about.

Anything I overlooked? Something different you use? Let me know.

Product-minded Rails notes

Once a month: straightforward notes on improving UX in Rails—what to simplify, what to measure, and UI/frontend changes that move real usage.

Over to you…

What did you like about this article? Learned something knew? Found something is missing or even broken? 🫣 Let me (and others) know!

Comments are powered by Chirp Form

Want to read me more?