memo_app

(4)Railsで簡単なメモアプリを作ってみる

masahide

14年間務めた大手自動車会社を退職 TECH CAMP短期集中コース受講 地元の自社、受託開発企業へ就職 やればできるを発信しています。

前回の作業で編集フォームと一覧表示が作成できました。

今回は削除機能を追加していきます。

destroyアクションの追加

config/routes.rb

Rails.application.routes.draw do
  root to: "memo#index"
  resources :memo, only: [:new, :create, :edit, :update, :destroy]
end

resourcesにdestroyアクションを追加

memo#destroyが追加されました。

ポイント

このようにroutes.rbを編集するとルーティングが生成され、機能への道筋を確保できるので機能追加時は忘れないうちにroutes.rbを編集した方がいいと思っています。

controllerにdestroyアクション追加

app/controllers/memo_controller

def destroy
   post = Post.find(params[:id])
   post.destroy
   redirect_to root_path
 end

updateとほぼ同じです。

1行目でレコードを指定
2行目で削除
3行目でトップページへ遷移

ビューページの作成

ビューの作成と行ってもeditの時と同じで削除機能のリンクを貼るだけです。

app/views/memo/index.html.erb

<h1>Memo app</h1>
 <% @posts.each do |post| %>
 <ul>
     <li>
       <%= post.content %>
       <%= link_to "編集", edit_memo_path(post) %>
       <%= link_to "削除", memo_path(post.id), method: :delete %>
     </li>
 </ul>
<% end %>
<%= link_to '新規投稿', '/memo/new' %>

ここで注目したいのがPrefixmethodです。Prefix:memo_path(post.id)はルーティングを確認していただくとわかりますがupdateと同じなんです。

あれ?何も書いてないじゃないか!
masahide(筆者)
これ実は省略されているだけで、全部memo_pathなんです。

僕は最初わからずPrefixではなく、Path(/memo/:id)使っていました。(汗

ポイント

method:method: :delete
ここでmethodを指定するとdestroyアクションが起動します。

ブラウザで確認すると削除機能が使えるようになりました。

リファクタリング

機能実装がある程度終わったら可読性を上げるために同じような記述をひとまとめにしていきます。

app/controllers/memo_controller.rb

def edit
   @post = Post.find(params[:id])
 end

 def update
   @post = Post.find(params[:id])
   @post.update(post_params)
   redirect_to root_path
 end
 
 def destroy
   @post = Post.find(params[:id])
   @post.destroy
   redirect_to root_path
 end

@post = Post.find(params[:id])この記述が3つあるのがわかります。こちらをひとまとめにしていきます。

private以下にset_postメソッドを追加します。

def set_post
   @post = Post.find(params[:id])
 end

before_actionを2行目あたりに追加します。

ポイント

before_action
すでに定義されている各アクションの実行前に作動してくれる。

class MemoController < ApplicationController
 before_action :set_post, only: [:edit, :update, :destroy]

 def index
   @posts = Post.all
 end

 def new
 end

 def create
   Post.create(post_params)
   redirect_to root_path
 end

 def edit
 end

 def update
   @post.update(post_params)
   redirect_to root_path
 end
 
 def destroy
   @post.destroy
   redirect_to root_path
 end

 private
 def post_params
   params.permit(:content)
 end

 def set_post
   @post = Post.find(params[:id])
 end

end

これで投稿した文を削除することができるようになりました。

エラーハンドリング

エラーハンドリング とはエラーが発生した時のアクションを決める事です。

例えば、今回の投稿機能に空文字不可を追加してみます。

バリデーションをかける

app/models/memo.rb

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

validatesはバリデーションと言って制約をかける事です。presence: trueをつける事で、存在している事!となります。

要約するとPostテーブルのcontentカラムには空で保存できない

実際にから文字を投稿指定見ると保存はできなくなりましたが、なぜ保存できなかったのかわかりません。

エラーハンドリング をする(create)

app/controllers/memo_controller.rb

def create
   @post = Post.create(post_params)
   if @post.save
     flash[:notice] = "投稿できました"
     redirect_to root_path
   else
     flash[:alert] = "文字を入力してください"
     redirect_to new_memo_path
   end
 end

createの部分をif文を使い、条件分岐します。saveできたらフラッシュメッセージ(投稿できました)を表示させトップページへ戻す

できなかったら(文字を入力してください)を表示させ新規投稿ページへ留める。

フラッシュメッセージの表示箇所の指定

app/views/layouts/application.erb

<body>
   <%= flash[:notice] %>
   <%= flash[:alert] %>
   <%= yield %>
 </body>

<%= yield %>より上に書くことで、各ページの上部に表示させることができます。実際に見てみましょう。

投稿成功

 

投稿失敗

こんな感じで投稿が成功したか、失敗したかがわかるようになりました。アラートっぽくするために、CSSを当ててみます。

app/views/layouts/application.erb

<body>
   <div class="notification">
     <div class="notice"><%= flash[:notice] %></div>
     <div class="alert"><%= flash[:alert] %></div>
   </div>
   <%= yield %>
 </body>

app/assets/stylesheets/memo.scss

.notification {
 .notice {
   background-color: blue;
   color: white;
   text-align: center;
 }

 .alert {
   background-color: orange;
   color: white;
   text-align: center;
 }
}

もう一度投稿を試すと、フラッシュに修飾されていることがわかります。

同じ要領でupdate(更新)もエラーハンドリング します。

エラーハンドリング をする(update)

app/controllers/memo_controller.rb

def update
   if @post.update(post_params)
     flash[:notice] = "投稿できました"
     redirect_to root_path
   else
     flash[:alert] = "文字を入力してください"
     redirect_to edit_memo_path(@post.id)
   end
 end

pathの指定

editなどurlにidが必要なページには引数を入れてあげれば大丈夫です。例えば (http://localhost:3000/memo/5/edit)にredirectさせるためにはPlefixのmemo_pathにidを渡すのでredirect_to edit_memo_path(@post.id)そして@postにはアップデートしたレコードが代入されているので、idだけを取り出し引数としました。

このまま削除もエラーハンドリング します。

エラーハンドリング する(delete)

app/controllers/memo_controller.rb

def destroy
   if @post.destroy
     flash[:delete] = "削除しました"
     redirect_to root_path
   else
     redirect_to root_path
   end
 end

app/assets/stylesheets/memo.scss

.notification {
 .notice {
   background-color:blue;
   color: white;
   text-align: center;
 }

 .alert {
   background-color: orange;
   color: white;
   text-align: center;
 }
 
 .delete {
   background-color: red;
   color: white;
   text-align: center;
 }
}

以上でエラーハンドリング は終了です。

なぜ条件分岐しないといけないの!?
masahide(筆者)
エラー発生時に下の表示をさせないためだよ

メモ

何か処理を行う時に成功した場合と失敗した場合を書いておかないと、実際に使用した時にエラー画面が表示されてしまう事になります。

プログラミングを学んでいない人が入力ミスでこんなエラー画面が出てきてしまったらびっくりしてしまうと思います。

ユーザビリティ向上していくことでより良いWEBアプリになっていくと思うので丁寧にエラーハンドリング して行きます。

ここまで読んでいただき、ありがとうございました。

おかしなコードがありましたらコメントしていただけると助かります。

 

-memo_app
-, , , ,

© 2020 まさブログ Powered by AFFINGER5