renderする部分テンプレートの内容を変える方法

renderする部分テンプレートの内容を変える方法

renderで共通で利用している部分テンプレートにおいて、どこからrenderするかによって部分テンプレートの内容を変えたい場合。

以下は、掲示板の新規登録画面ビューと編集画面ビューをそれぞれ共通の部分テンプレート[boards/_form.html.erb]をrenderして、フォームのクリックボタン表記に翻訳情報を与え、newアクションからrenderして読み込む場合と、editアクションからrenderして読み込む場合で、読み込む翻訳情報が変わるので、newアクションとeditアクションでのフォームのクリックボタン表記を変えたい場合の例です。

[app/views/boards/new.html.erb]

<% content_for(:title, (t '.title')) %>
<div class="container">
  <div class="row">
    <div class="col-lg-8 offset-lg-2">
      <h1><%= (t '.title') %></h1>
      <%= render partial: 'form', locals: { board: @board } %>
    </div>
  </div>
</div>

#掲示板の新規作成画面でnewのビューファイルから共通のformファイルを読み込んでいます。
[app/views/boards/new.html.erb]

<% content_for(:title, @board.title) %>
<div class="container">
  <div class="row">
    <div class="col-lg-8 offset-lg-2">
      <h1><%= (t '.title') %></h1>
      <%= render partial: 'form', locals: { board: @board } %>
    </div>
  </div>
</div>

#掲示板の編集画面でeditのビューファイルから共通のformファイルを読み込んでいます。

共通の部分テンプレートが以下になります。

[boards/_form.html.erb]

<%= form_with model: board, local: true do |f| %>
    <%= render 'shared/error_messages', { object: f.object } %>
    <div class="form-group">
      <%= f.label :title %>
      <%= f.text_field :title, class: "form-control" %>
    </div>
    <div class="form-group">
      <%= f.label :body %>
      <%= f.text_area :body, class: "form-control", rows: "10" %>
    </div>
    <div class="form-group">
      <%= f.label :image %>
      <%= f.file_field :image, onchange: 'previewImage()', class: 'form-control mb-3', accept: 'image/*' %>
      <%= image_tag board.image.url, id: 'preview', size: '300x200' %>
    </div>
    <%= f.submit (t '.button')class: "btn btn-primary" %>
<% end %>

翻訳ファイルが以下になります。

[locales/views/ja.yml]

ja:
  boards:
    new:
      button: '登録する'
    edit:
      button: '更新する'

予想している動き
[newアクションの場合] Boardsコントローラのnewアクションからの場合は、newビューより共通のformファイルを読み込む為、formファイル記載の( <%= f.submit (t '.button')class: "btn btn-primary" %>)の(t '.button')が翻訳ファイルのnewアクションに定義されているもので翻訳される。

[editアクションの場合] Boardsコントローラのeditアクションからの場合は、editビューより共通のformファイルを読み込む為、formファイル記載の( <%= f.submit (t '.button')class: "btn btn-primary" %>)の(t '.button')が翻訳ファイルのeditアクションに定義されているもので翻訳される。

上記を予想して実装しましたが、うまくいきませんでした。


解消した方法
共通の部分テンプレート[boards/_form.html.erb]を以下のように記述

[boards/_form.html.erb]

<%= form_with model: board, local: true do |f| %>
    <%= render 'shared/error_messages', { object: f.object } %>
    <div class="form-group">
      <%= f.label :title %>
      <%= f.text_field :title, class: "form-control" %>
    </div>
    <div class="form-group">
      <%= f.label :body %>
      <%= f.text_area :body, class: "form-control", rows: "10" %>
    </div>
    <div class="form-group">
      <%= f.label :image %>
      <%= f.file_field :image, onchange: 'previewImage()', class: 'form-control mb-3', accept: 'image/*' %>
      <%= image_tag board.image.url, id: 'preview', size: '300x200' %>
    </div>
    <% if board.new_record? %>     # if文で[new_record?]メソッドを使い表記を変えた部分
      <%= f.submit "登録する" ,class: "btn btn-primary" %>
    <% else %>
      <%= f.submit "更新するyo" ,class: "btn btn-primary" %>
    <% end %>
<% end %>

上記のようにすることで、newアクションとeditアクションのそれぞれでフォームのクリックボタンの表記を変えることができる。
[新規登録画面(newアクション)]
Image from Gyazo


[編集画面(editアクション)]
Image from Gyazo


※ポイント
[form_with]は、以下のようにボタン表記を入力しないとrailsが自動で予測してボタン表記を変えてくれるが、自分で表記を変えたい場合は、[new_record?]メソッドを使って表記を変える事ができる。

[form_withにボタン表記を入力しない場合]

[boards/_form.html.erb]

<%= form_with model: board, local: true do |f| %>
    <%= render 'shared/error_messages', { object: f.object } %>
    <div class="form-group">
      <%= f.label :title %>
      <%= f.text_field :title, class: "form-control" %>
    </div>
    <div class="form-group">
      <%= f.label :body %>
      <%= f.text_area :body, class: "form-control", rows: "10" %>
    </div>
    <div class="form-group">
      <%= f.label :image %>
      <%= f.file_field :image, onchange: 'previewImage()', class: 'form-control mb-3', accept: 'image/*' %>
      <%= image_tag board.image.url, id: 'preview', size: '300x200' %>
    </div>
      <%= f.submit class: "btn btn-primary" %>
<% end %>


[新規登録画面(newアクション)]
Image from Gyazo


[編集画面(editアクション)]
Image from Gyazo

[new_record?]メソッド
インスタンスが新規作成されてたらtrueを返す
インスタンスに既に情報が保存されている場合はfalseを返す

[パーシャルの中での翻訳情報の挙動]
パーシャルに入ると@virtual_pathという変数が書き換えられる。
lazy lookupは@virtual_pathの値を元に翻訳データにアクセスしているらしく、想定外の挙動になった。

参考記事: new_record?で場合分け ❏Rails❏ - Qiita

Surprising behavior with Rails I18n Lazy Lookups and Partials - DEV Community