View Component for Ruby on Rails

I'm a Ruby on Rails developer, building all my frontends with traditional html.erb files. I love Ruby, I love Rails, but I want to start using components to speed up my frontend. I'm looking to learn how.
Engineer at GitHub based in Louisville, CO
Follow this Taaalk

4 followers

1,070 views

Joshua Summers
17:27, 19 Jun 20 (edit: 23:19, 19 Jun 20)
Hi Joel ūüĎč
Thank you so much for Taaalking with me about View Component.
So to get things started, my whole website is RoR with standard views. This means my html.erb view files look a bit like this:
<h1><%= @tlk.title %><h1>

<%= render 'components/tlk_introduction' %>

<%= render 'components/conversation' %>
(And, obviously, behind all this sits my controllers, looking a bit like this:)
class TlksController < ApplicationController

  ...

  def show
    @tlk = Tlk.find(params[:id])
  end

  ...

end
Firstly, as I have a components folder within my views folder, am I using components already? Or are View Components different to that?
Joel Hawksley
22:43, 23 Jun 20
Hi, Joshua! This interview platform is pretty cool!
ViewComponents are different from traditional Rails views. 
A ViewComponent is a Ruby file and corresponding template file with the same base name:
app/components/test_component.rb:
class TestComponent < ViewComponent::Base
  def initialize(title:)
    @title = title
  end
end
app/components/test_component.html.erb:
<span title="<%= @title %>"><%= content %></span>
Rendered in a view as:
<%= render(TestComponent.new(title: "my title")) do %>
  Hello, World!
<% end %>
Returning:
<span title="my title">Hello, World!</span>
Most importantly, ViewComponents are encapsulated: the template code executes within the context of the Ruby object, unlike traditional Rails views which execute in a global context.
Joshua Summers
22:55, 24 Jun 20 (edit: 22:58, 24 Jun 20)
ūü§Į(but with a happy face). Mind blown.
OK so let's pick apart this...
Most importantly, ViewComponents are encapsulated: the template code executes within the context of the Ruby object, unlike traditional Rails views which execute in a global context.
When you say "the template code executes within the context of the Ruby object", what does this mean? 
As all I've ever known is the standard global way of doing things (to the point where I might not have considered there could be an alternative). Maybe an example comparing what's happening in the background for template code that executes within the context of the object, and template code that executes globally, would help me get to the bottom of what you're saying.
(P.S. Thank you re your kind words. Anyone can start a Taaalk about anything, so if you have some inquisitive friends, please send them Taaalk's way.)
Joel Hawksley
03:32, 02 Jul 20 (edit: 15:43, 07 Jul 20)
Good question! To say it another way, traditional Rails views are compiled into methods in a single, global context, which looks something like this:
class ViewContext
  def my_first_cool_view_html_erb
    ...
  end
  def my_second_cool_view_html_erb
    ...
  end
end
Because all the views in an application exist on the same object, they can share state! 
As Rails does not expose these methods as a public interface, we can’t test them directly either, meaning we end up testing them at the controller or integration test layer. If you have view code that is reused, such as partials, that often means duplicating your tests for each place you’re rendering the shared view code. 
ViewComponents, on the other hand, compile their templates onto their associated Ruby object, meaning that the template only has access to the state of the component object:
class MyComponent < ViewComponent::Base
  def initialize  
  end  

  def call
    # compiled Ruby code from template
  end
end
Since ViewComponents can be rendered directly, they are easily unit tested! Which in practice means that we’re more likely to test them thoroughly, and the duplication of tests is much less of an issue.
Joshua Summers
13:54, 10 Jul 20
Sweet, I see the improvement.
When people have Taaalked to me about React, it seems front end performance/the ability to generate a single page application is one of the key reasons behind choosing to use it.
Is ViewComponent built to exclusively improve the testing of views or is there a performance advantage to isolating views in this way?
Joel Hawksley
19:33, 21 Jul 20
Generally, yes, there is a performance improvement.
In production, ViewComponent templates are compiled when the application boots, unlike traditional Rails templates that are compiled the first time they are rendered. 
Joshua Summers
19:58, 30 Jul 20
That is cool.
Now moving to testing, would you mind giving me an example of tests you can write when you use ViewComponent, and perhaps (if you have time) what you'd have to do to test that same part of the view if you weren't using it? To get an understanding of the difference it makes.
Follow this Taaalk

4 followers

1,070 views

Start your own Taaalk, leave your details or meet someone to Taaalk with.