Webエンジニア目指して#39

どうもスマブラマンです。 新キャラ実装日ですね。ゼノブレ2やる前にホムラヒカリ来ちゃったな〜クリア後だったらすごいテンション上がってたと思います。
残すは2キャラ、一体何が来るんでしょう。アルルきて(切望)

さてProgateのRails Vやっていきましょう

バリデーションで空の投稿を防ぐ

データベースに保存されるデータをチェックし、意図しないものは弾くシステムのことをバリデーションという

モデルファイルに対して記述する

class Post < ApplicationRecord
  validates :message,{presence: true}
end

第2引数の{presence: true}が空の文字数を弾くバリデーション 第1引数のmessageカラムに対して動作する

これを記述した状態でmessageカラムが空のレコードを保存してみると、 f:id:misokatsu_sand:20210305110642p:plain falseと出て失敗する(本来はtrueと出て保存内容が表示される)

actionに組み込んでやるとそのままスルーする これで空の投稿や編集ができちゃう問題は解決

バリデーションで文字数制限
validates :message,{length: {maximum:140}}

{length: {maximum:140}の部分が文字数制限。
下のように他のバリデーションとまとめて書くことができる

validates :message,{presence: true,length: {maximum:140}}
バリデーションの結果で表示を変える

バリデーションに引っかかる状態でsaveメソッドを使ったらfalseを返すのを利用して、if文に組み込む

いつぞやの新規投稿actionを書き換える

def save
    @post=Post.new(message: params[:message])
    if @post.save
      redirect_to("/post/index")
    else
      redirect_to("/post/#{@post.id}/new")
    end
  end

if文の条件でしかsaveメソッドを書いてないがちゃんと実行した上で分岐をしてくれるらしい 結果はこんな感じ

f:id:misokatsu_sand:20210308133614g:plain

renderメソッド
render("controller名/viewファイル名")

routingアドレスを書かないように注意、viewファイルを直接参照する。接頭に/がないのにも注意
renderはviewを再描画する
redirectだと単純に再読み込みをするためactionの再実行によって入力した文字列が上書きされてしまうが、renderは定義や代入した変数は保持されるため、再描画直前の入力情報を表示させることが可能

以下の例のように、バリデーションで引っかかった際にrenderを使って直前の入力情報が表示されるようにする

投稿ページ(new.html.erb)

<div class="main">
<h1>新規投稿</h1>
<%= form_tag("/post/save") do %>
  <textarea name="message"><%= @post.message %></textarea>
  <input type="submit" value="投稿">
<% end %>
</div>

新規投稿画面だが再描画直前の入力を読み込ませるため、textareaに@post.messageを仕込んだ

saveアクション

def save
    @post=Post.new(message: params[:message])
    if @post.save
      redirect_to("/post/index")
    else
      render("post/new")
    end
end

バリデーションに引っかかりsaveがfalseを返したときにrenderで再描画をさせる
再描画時点では@post.messageは入力したレコードが代入されているため、viewで仕込んだtextareaに拾ってもらえる

newアクション

def new
    @post=Post.new()
end

viewに@postを書いているため、saveアクションが実行されるまでは定義されていない変数があることになり、最初にnewページを開いたときにエラーが出てしまう
これを防ぐために@postに空のレコードを入れておいた

投稿エラーメッセージを表示させる

下図のように、saveがfalseを返すときにレコード.errors.full_messagesの中にエラーメッセージが配列として入力される f:id:misokatsu_sand:20210308154705p:plain saveを実行するまではerrorsが空なことを利用してviewに仕込んでおく

<div class="main">
<h1>新規投稿</h1>
<% @post.errors.full_messages.each do |err| %>
  <%= err %>
<% end %>

<%= form_tag("/post/save") do %>
  <textarea name="message"><%= @post.message %></textarea>
  <input type="submit" value="投稿">
<% end %>
</div>

結果 f:id:misokatsu_sand:20210308161113g:plain なんか英語だがバリデーションの内容に対応したエラーメッセージが出ている、なんて便利なんだ

flash[:notice]

viewを一度表示したらnilにリセットされる変数。
保存に成功しました、みたいなメッセージ表示に使う

viewの上らへんにこんな感じで置いて、flash[:notice]に中身があるときだけ表示させる

<% if flash[:notice] != nil %>
        <div class="flash">
          <%= flash[:notice] %>
        </div>
<% end %>

saveアクションに仕込んでみた

def save
    @post=Post.new(message: params[:message])
    if @post.save
      flash[:notice]="新しく投稿しました"
      redirect_to("/post/index")
    else
      render("post/new")
    end
end

結果 f:id:misokatsu_sand:20210308174939g:plain

似たようなものを削除actionや編集actionに仕込んでRails Vはおしまい!ではでは。