LoginSignup
7
5

More than 5 years have passed since last update.

Rails Jbuilder の部分テンプレートに任意のファイルを使いたい

Last updated at Posted at 2018-08-08

きっかけ

親子関係のあるデータについて、親のエンドポイントにアクセスした時には親のデータとその親に紐づく子のデータを含めたい、そして子のデータだけにもアクセスできるようにしたい、ただ jbuilder を親と子で同じ内容を書くのが DRY じゃなくてダサい。json.partial! が使えそうだけど、他のディレクトリにあるテンプテートはどうやって呼び出すのかがググり力不足でわからず。

めっちゃ簡単なモデル

parent.rb
class Parent < ApplicationRecord
  has_many :children
end
child.rb
class Child < ApplicationRecord
  belongs_to :parent
end

ディレクトリ構成

views/
|-parents/
|  |-show.jbuilder
|-children/
   |-_detail.jbuilder
   |-show.jbuilder

parents/show.jbuilderchildren/_detail.jbuilder を呼び出したい

10分ググり続けてもマニュアルが見当たらなかったのでソースコードを読んだ。
https://github.com/rails/jbuilder/blob/ad01e8496e1b4c537314a2b74a76dfb4594f67bf/lib/jbuilder/jbuilder_template.rb

上記クラスの _render_explicit_partial メソッドに、テンプレートのviewから見たパスと、渡したい変数を locals で渡せれば良さそう。

jbuilder_template.rb
def partial!(*args)
  if args.one? && _is_active_model?(args.first)
    _render_active_model_partial args.first
  else
    _render_explicit_partial(*args)
  end
end

# 中略

private

# 中略

def _render_explicit_partial(name_or_options, locals = {})
  case name_or_options
  when ::Hash
    # partial! partial: 'name', foo: 'bar'
    options = name_or_options

# 以下略

コメントにあるように json.partial! partial: 'name', foo: 'bar' の形で使ってあげれば良さそう。

結論

こう書きました。

parents/show.jbuilder
json.id(@parent.id)
json.set! :children do
  json.array!(@parent.children) do |child|
    json.partial! partial: 'children/detail', locals: { child: child }
  end
end
children/_detail.jbuilder
json.id(child.id)

んでAPI叩く。

curl -X GET http://localhost:3000/parent/1
{
  "id": 1,
  "children": [
    { "id": 1 },
    { "id": 2 }
  ]
}

動きました:)

追記

普通にreadme.md に書いてありました…ググり力が足りなすぎる…

7
5
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
7
5