ERBでHTMLを作る
ERBはHTMLの中へRubyの値や繰り返しを埋め込むテンプレートです。表示する値には出力タグ、処理だけには処理タグを使います。
<h1>記事一覧</h1>
<% @articles.each do |article| %>
<article>
<h2><%= link_to article.title, article_path(article) %></h2>
<p><%= truncate(article.body, length: 80) %></p>
</article>
<% end %>link_toなどのヘルパーを使うと、URLの書き間違いを減らせます。表示用の加工はヘルパーやプレゼンテーション層へまとめ、複雑な処理をビューに増やさないようにします。
フォームを作る
<%= form_with model: article do |form| %>
<div>
<%= form.label :title, "タイトル" %>
<%= form.text_field :title %>
</div>
<div>
<%= form.label :body, "本文" %>
<%= form.text_area :body, rows: 8 %>
</div>
<%= form.submit "保存" %>
<% end %>新規作成と編集で同じ部分テンプレートを使えば、入力欄の変更を一か所で済ませられます。ファイル名の先頭のアンダースコアは部分テンプレートを表します。
入力エラーを表示する
<% if article.errors.any? %>
<div>
<h2><%= article.errors.count %>件のエラーがあります</h2>
<ul>
<% article.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>1件のエラーがあります
Title can't be blank保存に失敗したときはrender :newでフォームを再表示します。redirect_toを使うと別リクエストになり、モデルのエラー情報が失われるため、入力エラーの再表示には通常renderを使います。
Strong Parameters
受け取ったパラメーターの全項目をそのまま保存しません。保存してよい属性をコントローラーで明示します。
private
def article_params
params.require(:article).permit(:title, :body)
end編集と削除を画面から行う
新規作成と編集は同じ部分テンプレートを使えます。編集画面では既存のArticleを渡すと、フォームヘルパーがPATCH送信の形を作ります。
def edit
@article = Article.find(params[:id])
end
def update
@article = Article.find(params[:id])
if @article.update(article_params)
redirect_to @article
else
render :edit, status: :unprocessable_entity
end
end<h1>記事を編集</h1>
<%= render "form", article: @article %>PATCH /articles/3
更新しました
GET /articles/3保存に失敗したときは同じ編集画面へ戻し、入力値とエラーを失わないようにします。
フラッシュメッセージとレイアウト
redirect後に一度だけ表示するメッセージはflashへ入れ、レイアウトで共通表示します。
redirect_to articles_path, notice: "記事を削除しました"
redirect_to @article, alert: "保存できませんでした"<% if notice %>
<p class="notice"><%= notice %></p>
<% end %>
<% if alert %>
<p class="alert"><%= alert %></p>
<% end %>記事を削除しましたフォームの安全性を確認する
入力欄の表示、サーバー側のバリデーション、Strong Parametersは役割が違います。画面のJavaScript検証だけでは不十分なので、必ずモデルとコントローラーでも確認します。
def article_params
params.require(:article).permit(:title, :body)
end<p><%= article.body %></p>
<!-- html_safeを無条件に使わない -->利用者が入力したHTMLを許可する機能が必要なら、許可するタグを限定してサニタイズします。表示を簡単にするために安全機構を無効化しないことが重要です。
練習問題
問題:文字数を表示する
記事本文の文字数を表示し、本文がないときは「本文なし」と表示してください。
<% if article.body.present? %>
<p>文字数:<%= article.body.length %></p>
<% else %>
<p>本文なし</p>
<% end %>