ここではツイートの削除機能を追加する。
データの削除はRailsの基本機能の1つであるため、使いこなせるようにしたい。
ツイートの削除機能を追加する
現在の実装では一度投稿したツイートは削除することができない。
そこで、ツイートに削除ボタンを追加して、ツイートの削除を行えるようにする。
ツイートを削除する流れは、下記の図のような流れで実行される。
作業手順はルーティングを設定することでビューに削除のパスを指定できるため、ルーティングの編集から始まる。
作業内容
1.ツイートを削除するためのルーティングを設定する
2.削除ボタンをビューに追加する
3.destroyアクションをコントローラに定義する
4.削除後のビューを追加する
1.ツイートを削除するためのルーティングを設定する
ツイート削除機能を実装するためにまずはルーティングを定義していく。
ツイートを削除する際にはツイートごとに固有のパスが発行されるので、ユーザーのマイページを作成したときと同様に少し特別なルーティングが必要になる。
また、ツイートの削除を行う際にはdeleteというHTTPメソッドを利用する。
deleteメソッド
HTTPリクエストにはいくつかの種類があり、これまでにgetメソッドとpostメソッドを学習した。
deleteメソッドは情報の削除を行う際に利用するHTTPメソッドである。
今回の場合、ツイートの削除を行うのでdeleteメソッドを利用する。
また、ツイートの削除を行う際には、tweetsコントローラのdestroyアクションを動かす。
config/routes.rbを以下のように編集する
config/routes.rb
Rails.application.routes.draw do devise_for :users root 'tweets#index' get 'tweets' => 'tweets#index' get 'tweets/new' => 'tweets#new' post 'tweets' => 'tweets#create' delete 'tweets/:id' => 'tweets#destroy' get 'users/:id' => 'users#show' end
リクエストする箇所(ビュー)では、パスの:idの部分に削除するツイートのidが入るように記述する。
すると、パラメーターがコントローラに渡る際paramsのキーにidが追加され、そのバリューはリクエストの際に:idの部分に記述された値になる。
つまり、:idの部分に記述された値はコントローラ上でparams[:id]とすることで取得できる。
2.削除ボタンをビューに追加する
ツイートを削除するためにビューファイルを編集して削除ボタンを追加する。
今回は、link_toメソッドを使用する。
削除ボタンはツイートの表示画面の右上に配置される。
また、自分が投稿したツイートにのみ表示されるようにする。
link_toメソッドを実装する際にはrake routesコマンドを使用して、パスを確認する必要がある。
必ずしもrake routesで確認する必要性はなく、指定するパスを忘れてしまった場合にコマンドを実行する。
rake routes
このコマンドは現在定義しているルーティングを表示してくれるコマンドである。
ターミナルで入力することで、config/routes.rbに記述したルーティングを表示してくれる。
【例】
ターミナル
$ rake routes
|
出力結果
Prefix Verb URI Pattern Controller#Action
new_user_session GET /users/sign_in(.:format) devise/sessions#new
user_session POST /users/sign_in(.:format) devise/sessions#create
destroy_user_session DELETE /users/sign_out(.:format) devise/sessions#destroy
user_password POST /users/password(.:format) devise/passwords#create
new_user_password GET /users/password/new(.:format) devise/passwords#new
edit_user_password GET /users/password/edit(.:format) devise/passwords#edit
PATCH /users/password(.:format) devise/passwords#update
PUT /users/password(.:format) devise/passwords#update
cancel_user_registration GET /users/cancel(.:format) devise/registrations#cancel
user_registration POST /users(.:format) devise/registrations#create
new_user_registration GET /users/sign_up(.:format) devise/registrations#new
edit_user_registration GET /users/edit(.:format) devise/registrations#edit
PATCH /users(.:format) devise/registrations#update
PUT /users(.:format) devise/registrations#update
DELETE /users(.:format) devise/registrations#destroy
root GET / tweets#index
tweets GET /tweets(.:format) tweets#index
POST /tweets(.:format) tweets#create
new_tweet GET /tweets/new(.:format) tweets#new
tweet DELETE /tweets/:id(.:format) tweets#destroy
user GET /users/:id(.:format) users#show
|
rake routesコマンドを実行すると例えば上記のような出力結果が表示される。(完全に同様の出力結果でなくてもOK)
この出力結果は以下のような意味を持っている。
項目名 | 意味 |
---|---|
Prefix | 「Prefix」はルーティングの名前を表しています。「Prefix」は設定を行わなくても、自動的に割り当てられますが、自ら設定することもできます。 |
Verb | 「Verb」はHTTPメソッドを表しています。右側に表示されているパスにどのHTTPメソッドでアクセスするかを示しています。 |
URI Pattern | 「URI Pattern」はルーティングのパスを表しています。このパスにアクセスされた際に、指定のコントローラとアクションで処理が行われます。 |
Controller#Action | 「Controller#Action」は指定したパスにアクセスした際に処理が行われるコントローラとアクションを表しています。#以前がコントローラ名、#以後がアクション名を示しています。 |
また、/tweets(.:format) の後ろについている(.:format)とは、formatオプションとよばれるもので、html形式やjson形式といった複数の形式で出力することができるというものである。
このカリキュラムでは、すべてhtml形式を使用しますので、現時点ではいろいろな形式があるのだな、程度の認識で問題ない。
問題1:削除ボタンを作成しましょう
作業ファイル:app/views/tweets/index.html.erb
ヒント1:下記の例をもとに、link_toメソッドを利用しましょう。
ヒント2:rake routesで確認した、tweetsコントローラのdestroyメソッドを動かすhttpメソッド/パスの組み合わせを書きましょう
ヒント3:Rubyタグの中の文字列内で変数を使いたい場合は式展開#{}を使用します。
ヒント4:削除したいツイートを投稿したユーザーのidは変数`tweet`を使用して取得します。
【例】//省略 <div class="content_post" style="background-image: url(<%= tweet.image %>);"> <% if ユーザーがログインしているか? かつ current_user.id == 削除したいツイートを投稿したユーザーのid %> <div class="more"> <span><%= image_tag 'arrow_top.png' %></span> <ul class="more_list"> <li> <%= link_to '削除', "/tweets/削除したいツイートのid", method: :HTTPメソッドを指定 %> </li> </ul> </div> <% end %> <%= simple_format(tweet.text) %> <span class="name"> <a href="/users/<%= tweet.user_id %>"> <span>投稿者</span><%= tweet.user.nickname %> </a> </span> </div> //省略
【 問題1の解答を確認する 】
3.destroyアクションをコントローラに定義する
ツイートを削除する際にはtweetsコントローラのdestroyアクションを動かす。
そこで、このアクションをコントローラに定義していく。
destroyメソッド
ActiveRecordメソッドのうちの一つで、インスタンスに対してそのレコードを削除する際に使うことができる。
ターミナルで実行して確認してみる。
以下の指示に従い、ターミナルからコマンドを実行する。
ターミナル
$ rails c
[1] pry(main)> tweet = Tweet.find(tweetsテーブルを見て保存されているidを入力してください)
=> #<Tweet:0x007ff621357720 id: 1, name: "george", text: "いい景色だ", image: "http://photo1.jpg", created_at: Thu, 16 Apr 2015 05:41:20 UTC +00:00, updated_at: Thu, 16 Apr 2015 05:41:20 UTC +00:00, user_id: 1>]
[2] pry(main)> tweet.destroy
|
すると、以下のような結果になり、レコードが削除される。
ターミナル
(0.2ms) BEGIN SQL (1.6ms) DELETE FROM `tweets` WHERE `tweets`.`id` = 1 (0.3ms) COMMIT => #<Tweet:0x007ff621357720 id: 1, name: "george", text: "いい景色だ", image: "http://photo1.jpg", created_at: Thu, 16 Apr 2015 05:41:20 UTC +00:00, updated_at: Thu, 16 Apr 2015 05:41:20 UTC +00:00, user_id: 1>]
tweets_controllerにdestroyアクションを実装していく。
ツイートを削除する際にはdestroyメソッドを使う。
また、どのツイートを削除するのかを特定する場合はparams[:id]を使用して、削除したいツイートの情報を取得する。
削除を行えるのは、そのツイートを投稿したユーザーのみである。
そのため、別のユーザーが削除をできないように条件をつける必要がある。
app/controllers/tweets_controller.rbを以下のように編集する
app/controllers/tweets_controller.rb
class TweetsController < ApplicationController before_action :move_to_index, except: :index def index @tweets = Tweet.includes(:user).page(params[:page]).per(5).order("created_at DESC") end def new end def create Tweet.create(image: tweet_params[:image], text: tweet_params[:text], user_id: current_user.id) end def destroy tweet = Tweet.find(params[:id]) if tweet.user_id == current_user.id tweet.destroy end end private def tweet_params params.permit(:image, :text) end def move_to_index redirect_to action: :index unless user_signed_in? end end
後置if
最後のendを省略してif文を処理の後方に配置する書き方である。
elsif, elseにあたる条件分岐が無く、かつ処理が一行で完結する場合に用いる。
コード量も少なくシンプルに記述できるので、今回のdestroyメソッドは以下のように書き直す。
app/controllers/tweets_controller.rb
def destroy tweet = Tweet.find(params[:id]) tweet.destroy if tweet.user_id == current_user.id end
4.削除後のビューを追加する
ルーティングとコントローラの編集が終わったため、続いてビューファイルの追加を行う。
このビューファイルはツイートの削除を行ったあとに呼び出されるビューファイルになる。
以下の指示に従い、app/views/tweets/destroy.html.erbを作成する
①ファイルの新規作成
app/views/tweetsディレクトリの中にdestroy.html.erbというファイルを作成する。
②ファイルの編集
作成したファイルを、以下のように編集する。
app/views/tweets/destroy.html.erb
<div class="contents row"> <div class="success"> <h3> 削除が完了しました。 </h3> <a class="btn" href="/">投稿一覧へ戻る</a> </div> </div>
このソースコードは、打ち間違いを防ぐためにコピー&ペーストでOK
トップページを開き、削除機能を試してみる
① ログインする
② ログインしたユーザーでツイートの投稿する。一番上に表示されます。
③ 削除ボタンをクリックする。