はじめに
この記事はCODEBASE OKINAWA Advent Calendar 2022 15日目の記事です。今回は自分が今プロジェクトで書いている Ruby on Rails のライブラリViewComponent の導入の仕方やメリットについて書いていきます
ViewComponent とは
Rails 6.1 からデフォルトでサポートされるようになったgithub製のgemrender partialという部分テンプレートが使用できるライブラリのより便利になったもので Componentベースで開発するのでコードの再利用が簡単でテストもしやすいです
公式ドキュメント
https://github.com/github/view_component
始め方
まずはgemを追加します。gem "view_component", require: "view_component/engine"
componentを生成
今回は下記のようなボタンを試しに作ります。
rails generate component コンポーネント名 引数
のコマンドを使用すればコンポーネント名とそこに渡す引数を指定して実行します
ボタンを作成するので今回は引数によって色が変わるようにcolor
を引数に使用します。
bin/rails g component Button color
Running via Spring preloader in process 68330
create app/components/button_component.rb
invoke rspec
create spec/components/button_component_spec.rb
invoke erb
create app/components/button_component.html.erb
app/componentsというディレクトリが作成されるのでその下に .rb と html.erb ファイルが生成されます。
app/components/
├── button_component.html.erb
└── button_component.rb
※ちなみにcomponentはパーツごとに作成すると思うので実際はディレクトリごとに分けて作成していくことが多いです。
app/components/
├── button
├── component.html.erb
└── component.rb
rails generate component で指定したcolor が引数として initializeに渡されます。
# frozen_string_literal: true
class ButtonComponent < ViewComponent::Base
def initialize(color:)
@color = color
end
end
ボタンの部分をコンポーネント化
app/components/button_component.html.erbにボタン部分の実装を切り出しますcolor
オブジェクトは ButtonComponent
の @color
が利用できます。
(ボタンの色なのでclass属性内で呼び出しています)
<a href=“#” class="text-center relative py-4 border border-gray-300 rounded-lg
<%= @color %><%= border_color %><%= background_color %>” >
黒テキスト
</a>
コンポーネントの呼び出し側の一覧画面では render メソッドの引数として ButtonComponent.new(color: color)
を渡す
<div class="w-full border-b border-gray-300 pb-8 mb-8">
<%= render(ButtonComponent.new(color: color)) %>
</div>
部品や関数の実装
上記のbutton_component.html.erbで記述したborder_color
は 以前Helperなどに書いていたメソッドですが、それらもComponent内に書くことができます。
そこで定義したメソッドはerbでそのまま呼び出せます。
class IdeaComponent < ViewComponent::Base
...
+ def border_color
+ @color.border_color ? 'border-yellow-800' : 'border-black'
+
+ end
end
ViewComponent を使うメリット
一番はテストやデバッグがしやすいことでした。
ViewComponentであればE2Eテストを書く必要はありませんし、コンポーネントごとにテストが可能です
require "view_component/test_helpers"
RSpec.configure do |config|
config.include ViewComponent::TestHelpers, type: :component
end
ButtonComponent では下記のように書きます。
require "rails_helper"
RSpec.describe ButtonComponent, type: :component do
let(:color) { Idea.new(background_color: ‘bg-‘white ) }
subject(:component) { render_inline(described_class.new(color: color)) }
it “背景色を”設定 do
expect(component.css("h4").to_html).to include color.background_color
end
end
まとめ
ViewComponentを使用するまでRails自体ほとんど書いたことなかったのですが、フロントエンジニアでもRailsでコンポーネントベースで開発ができる学習コストの低さも魅力です。
今回作成したボタンのtext や label をダイナミックに切り替えるのにReactを併用したりもできるので使い方の幅も広そうです。