LoginSignup
44
42

More than 3 years have passed since last update.

【Rails 部分テンプレート(render partial)を用いたviewを別コントローラから呼び出す(render template)】

Last updated at Posted at 2019-07-26

はじめに

業務にて、コントローラ(1)のアクションAでview(a)を表示するためにrenderを使い、別コントローラ(2)のアクションBで呼び出されるview(b)を呼び出した。しかし、view(b)は部分テンプレートを使っておりview(a)が上手く表示されない……という事態に。
解決できたのでメモしておきます。

[前提1] コントローラ内で使う renderメソッド

renderメソッドは、コントローラのアクション内で呼び出すview(テンプレート)を指定します。
他に使われることの多いredirect_toは、指定したURLへ直接リダイレクトされます。

renderメソッドにはオプションが複数あります。

同一コントローラ内の他のアクションに対応するviewを呼び出す場合 [render action]
admin_controller.rb
#app/views/admin/edit.html.erbを呼び出す
def update
  if @post.save
    redirect_to('/admin/index')
  else
    render action: :edit
end
レイアウトを指定して呼び出す場合[render layout]
admin_controller.rb
#app/views/layouts/hoge.html.erbをレイアウトとして呼び出す
def edit
  @article = Posts.find_by(id: params[:id])
  render layout: 'hoge'
end
別のコントローラーのアクションに対応するviewを呼び出す場合[render template: 'コントローラ名/アクション名']
admin_controller.rb
#app/views/home/indexを呼び出し、app/views/layouts/hoge.html.erbをレイアウトとして呼び出す
def preview
  render template: 'home/index', layout: 'hoge'
end

本題では3つ目のrender templateを使います。

他にもjsonを返すrender jsonや、アプリケーション外のテンプレートを表示するrender fileなどがあります。(http://railsdoc.com/references/render)

[前提2] 部分テンプレート viewで用いるrender partial

viewで繰り返し表示するパーツや、共通のパーツは部分テンプレートにまとめることができます。
ここではpostモデルにtitleカラムを持つものとします。

app/views/home/index.html.erb
<div>
<%@posts.each do |post|%>
...
  <div>
  <%= render partial: "title", locals: { title: post.title }%>
  </div>
...
<%end%>
</div>
app/views/home/_title.html.erb
<p>タイトルは<%=title %>です</p>

view内での書き方は、
render partial: "呼び出すファイル名", locals:{ local変数(呼び出すファイル内で用いる変数名): 渡す値 }です。

[本題] 部分テンプレート(render partial)を用いたviewを別コントローラから呼び出したい

ここからが本題です。
[前提1]の3つ目の例と[前提2]の2つのファイルを使います。

・コントローラ

admin_controller.rb
#app/views/home/indexを呼び出し、app/views/layouts/hoge.html.erbをレイアウトとして呼び出す
def preview
  render template: 'home/index', layout: 'hoge'
end

・呼び出すview(テンプレート)

app/views/home/index.html.erb
<div>
<%@posts.each do |post|%>
...
  <div>
  <%= render partial: "title", locals: { title: post.title }%>
  </div>
...
<%end%>
</div>

まずは、admin_controllerのpreviewアクションに対応するviewを作ります。

app/views/admin/preview.html.erb
#app/views/home/index.erbがテンプレートとして入ります。何も記入しなくてOKです。

これだけだと、'title'というviewが見つからないとエラーが出てしまいました・・・。
コントローラにrender partial: 'home/titleを追加してみるもエラー。

試しに、app/views/admin/_title.html.erbというファイルを作ってみると、エラーは解消されたが何も表示されず。

中身を表示させてしまえば良いのかと思い、ここでも部分テンプレートを使ってみることに。

app/views/admin/_title.html.erb
<%= render partial: "home/title", locals: { title: post.title }%>

これで無事に内容が表示されました。
別コントローラの部分テンプレートを用いる際はrender partial "コントローラ名/ファイル名"で良さそうです。
"home/_title"では上手くいきませんでしたのでアンダーバーは不要…。

まとめ

部分テンプレート(render partial)を用いたviewを別コントローラから呼び出す際は、
1.アクションに対応するviewファイルを作る
2.呼び出すviewの部分テンプレートと同名のviewファイルを作る
3.2で作ったファイルで、元の部分テンプレートを呼び出す

終わりに

render templateしたら、呼び出した先の部分テンプレートも連れてきてくれるものだと勝手に思っていたので勉強になりました。
初心者ですので、間違っている点や他の方法等あればご指摘いただけますと幸いです。

44
42
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
44
42