6
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

ViewComponentを使ってRubyでコンポーネント開発

Last updated at Posted at 2022-12-15

はじめに

この記事はCODEBASE OKINAWA Advent Calendar 2022 15日目の記事です。
今回は自分が今プロジェクトで書いている Ruby on Rails のライブラリViewComponent の導入の仕方やメリットについて書いていきます

ViewComponent とは

Rails 6.1 からデフォルトでサポートされるようになったgithub製のgem
render partialという部分テンプレートが使用できるライブラリのより便利になったもので Componentベースで開発するのでコードの再利用が簡単でテストもしやすいです
公式ドキュメント
https://github.com/github/view_component

始め方

まずはgemを追加します。
gem "view_component", require: "view_component/engine"

componentを生成
今回は下記のようなボタンを試しに作ります。

スクリーンショット 2022-12-15 11.02.45.png

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に渡されます。

app/components/button_component.rb
# 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属性内で呼び出しています)

app/components/button_component.html.erb

<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) を渡す

app/views/inquiry/index.html.erb
<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でそのまま呼び出せます。

app/components/button_component.rb
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を併用したりもできるので使い方の幅も広そうです。

6
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?