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アクション)]
※ポイント
[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_record?]メソッド
・インスタンスが新規作成されてたらtrueを返す
・インスタンスに既に情報が保存されている場合はfalseを返す
[パーシャルの中での翻訳情報の挙動]
パーシャルに入ると@virtual_pathという変数が書き換えられる。
lazy lookupは@virtual_pathの値を元に翻訳データにアクセスしているらしく、想定外の挙動になった。
参考記事: new_record?で場合分け ❏Rails❏ - Qiita
Surprising behavior with Rails I18n Lazy Lookups and Partials - DEV Community