Upgrade to Pro — share decks privately, control downloads, hide ads and more …

render 出来るオブジェクトの作り方

Tomoya Chiba
December 20, 2023
160

render 出来るオブジェクトの作り方

Gotanda.rb#56 (https://gotanda-rb.connpass.com/event/304333/) で発表した資料です

Tomoya Chiba

December 20, 2023
Tweet

Transcript

  1. 千葉 知也 (@tomoasleep) Qiita 株式会社 エンジニア 五反田 のオフィスから来ました SNS (?)

    https://twitter.com/nemunemu3desu https://qiita.com/tomoasleep 自己紹介 2
  2. 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
  3. 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
  4. 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
  5. https://viewcomponent.org/ 再利用性の高い View のパーツを実装するためのフレームワーク render に monkey patch をして ViewComponent

    を渡せるようにしていたが、そ れが Rails 本体に取り込まれた class MessageComponent < ViewComponent::Base erb_template <<-ERB <h1>Hello, <%= @name %>!</h1> ERB def initialize(name:) @name = name end end <%= render(MessageComponent.new(name: "World")) %> 機能の背景 : ViewComponent 8
  6. 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
  7. タイトルを設定、 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
  8. 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
  9. 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