Slide 1

Slide 1 text

Tomoya Chiba (@tomoasleep) render 出来るオブジェクトの作り方 1

Slide 2

Slide 2 text

千葉 知也 (@tomoasleep) Qiita 株式会社 エンジニア 五反田 のオフィスから来ました SNS (?) https://twitter.com/nemunemu3desu https://qiita.com/tomoasleep 自己紹介 2

Slide 3

Slide 3 text

今日話すこと 3

Slide 4

Slide 4 text

↓ これ (render できるオブジェクト) について話します <%= render HelloPage.new %> 今日話すこと 4

Slide 5

Slide 5 text

class HelloComponent def render_in(view_context) view_context.content_for(:title, "Hello") view_context.content_tag(:p, "Hello, World!") end end <%= render HelloComponent.new %> Rails 6.1 で追加された機能 Introduce support for 3rd-party component frameworks by joelhawksley · Pull Request #36388 · rails/rails で追加 render_in メソッドを実装しているオブジェクトを渡せる render_in メソッドの引数には ActionView::Base のインスタンスが渡さ れる 返り値が表示する内容になる render にオブジェクトを渡せるようになった 5

Slide 6

Slide 6 text

Controller から render するには format メソッド も必要 layout は通常通り適用される class HelloPage def render_in(view_context) view_context.content_for(:title, "Hello") view_context.content_tag(:p, "Hello, World!") end def format :html # どの format かを指定 end end class HelloController def index render HelloPage.new # render renderable: HelloPage.new でも可 end end Controller からも呼べる 6

Slide 7

Slide 7 text

class HelloJSON def render_in(view_context) '{ "type": "json" }' end def format :json end end class HelloController def index render HelloJSON.new end end $ curl -i localhost:3000 HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8 { "type": "json" } 例 : Content-Type もいじれる 7

Slide 8

Slide 8 text

https://viewcomponent.org/ 再利用性の高い View のパーツを実装するためのフレームワーク render に monkey patch をして ViewComponent を渡せるようにしていたが、そ れが Rails 本体に取り込まれた class MessageComponent < ViewComponent::Base erb_template <<-ERB

Hello, <%= @name %>!

ERB def initialize(name:) @name = name end end <%= render(MessageComponent.new(name: "World")) %> 機能の背景 : ViewComponent 8

Slide 9

Slide 9 text

partial などに不満があり、Ruby でガッツリ View を実装したい場合 → ViewComponent をまず検討したほうが良いと思う ViewComponent の機能をそこまで使うことがないケース → 内製してしまうのもありかも ( この後紹介) render 出来るオブジェクトを何で作るか 9

Slide 10

Slide 10 text

Qiita では Rails の View → React での View への移行を進めている すると Rails 側の View 実装がスカスカに 変数をバケツリレーするだけの冗長なコードに <% content_for :title, "Page Title" # タイトルを指定 content_for :description, "Description" # meta tag とかの項目を指定 component = react_component( # React on Rails の機能で React Component を埋め込む 'HelloReactPageComponent', props: { item: @item, user: @user, }, ) %> <%= component %> Qiita での実用例 10

Slide 11

Slide 11 text

タイトルを設定、 React Component を埋め込むだけのパターン化した View を Render するためのクラスを定義 class ReactView def initialize(component, title:) @component = component @title = title end def render_in(view_context) view_context.content_for(:title, @title) view_context.react_component( @component.name, props: @component.props, ) end end 定型化した View を render 出来るオブジェクトとし て実装 11

Slide 12

Slide 12 text

Controller から直接 React の View を埋め込めるように class HelloController def index render ReactView.new( HelloReactPageComponent.new( props: { item: @item, user: @user, }, ), title: "Page Title", description: "Description", ) end end Qiita での使い方 12

Slide 13

Slide 13 text

render_in を定義したオブジェクトは render に渡すことが出来る View をガッツリ実装するには ViewComponent がおすすめだが… 定型化された薄い View を切り出すには便利かも まとめ 13

Slide 14

Slide 14 text

Introduce support for 3rd-party component frameworks by joelhawksley · Pull Request #36388 · rails/rails https://github.com/rails/rails/pull/36388 Rails 6.1 の Renderable objects でお手軽に脱 ERB する #Ruby - Qiita https://qiita.com/tomoasleep/items/5c1cf71c1148c2737ca2 実装を見たい rails/rails で Renderable, render_in を検索 References 14