view_componentとは
github製のgemです。
https://github.com/github/view_component
render partialのパワーアップ版みたいなもので、viewのコードを再利用したい時やテストを書きたい時に便利そうです。
こんな感じでrubyとtemplateをセットで用意できるので、partialに比べてロジックやデータの受け渡しが書きやすそうです。
class TestComponent < ViewComponent::Base
def initialize(title:)
@title = title
end
end
<span title="<%= @title %>"><%= content %></span>
呼び出すときはこんな感じです。
<%= render(TestComponent.new(title: "my title")) do %>
Hello, World!
<% end %>
定義した @title
とは別に、blockで渡した内容は自動的に content
というaccessorに割り当てられます。
インストール
gemを追加して bundle install
でインストールできます。
gem "view_component", require: "view_component/engine"
バージョンについて
rails5.0以上で動くようです。
ただしrails6.1未満だとrenderメソッドにモンキーパッチが当たるようです。
モンキーパッチを当てたくない場合は render_component
を使うこともできます。
config.view_component.render_monkey_patch_enabled = false # defaults to true
<%= render_component Component.new(message: "bar") %>
view_componentの作成
railsコマンドでview_componentを作成してみます。
bin/rails generate component Example title
こんな感じでファイル一式が作成されます。
Running via Spring preloader in process 407
create app/components/example_component.rb
invoke test_unit
create test/components/example_component_test.rb
invoke erb
create app/components/example_component.html.erb
preview機能
ActionMailerのようにview_componetをpreviewで確認できます。
class TestComponentPreview < ViewComponent::Preview
def with_default_title
render(TestComponent.new(title: "Test component default"))
end
def with_long_title
render(TestComponent.new(title: "This is a really long title to see how the component renders this"))
end
def with_content_block
render(TestComponent.new(title: "This component accepts a block of content")) do
tag.div do
content_tag(:span, "Hello")
end
end
end
end
これで下記のurlにアクセスするとpreviewを確認できるようになります。
http://localhost:3000/rails/view_components/test_component/with_default_title
http://localhost:3000/rails/view_components/test_component/with_long_title
http://localhost:3000/rails/view_components/test_component/with_content_block
テストの書き方
render_inline
でview_componentを呼び出して、内容をテストできます。
require "test_helper"
class HelloComponentTest < ViewComponent::TestCase
def test_component_renders_something_useful
assert_equal(
%(<div>hello bob</div>),
render_inline(HelloComponent.new(name: "bob")).css("div").to_html
)
end
end
ドキュメント
今回紹介したもの以外にも色々機能があるようなので気になる方は公式ドキュメントをご覧ください。
https://viewcomponent.org/