さらなる高みへ -higher ground -

プログラミング学習の定着を狙いとしたアウトプット(独り言)をしてみるブログ

ツイートの編集機能をつける

ここでは、ツイートの編集ができるようにする。
前章の削除に引き続き、編集もRailsの基本的な機能である。

ツイートの編集機能を追加する

今回の作業ではツイートの編集機能を実装する。
編集を行う際には編集ページを用意して、そのページから編集を行うようにする。

作業内容

1.ツイート編集画面のルーティングを設定する

2.編集ボタンをビューに追加する

3.editアクションをコントローラに定義する

4.編集画面のビューファイルを作成する

5.ツイートの更新を行うためのルーティングを設定する

6.updateアクションをコントローラに定義する

7.更新後のビューファイルを追加する

1.ツイート編集画面のルーティングを設定する

ツイートを編集する際は、ツイートを編集するための画面に遷移したあとに、ツイートの編集を行う。
今回の作業では、編集画面へ遷移するためのルーティングを設定する。
編集画面への遷移にはコントローラtweetsコントローラのeditアクションを動かす。

また、編集画面のパスはツイートごとに異なるものになるため、destroyメソッドの時と同じように:idのような書き方を利用する。

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   'tweets/:id/edit'  => 'tweets#edit'
  get   'users/:id'  =>  'users#show'
end

2.編集ボタンをビューに追加する

ツイートを編集する画面に遷移するためのボタンを作成する。
編集ボタンは、削除ボタンの上に表示されるようにする。

削除ボタンと同じように、link_toメソッドを使用する。

app/views/tweets/index.html.erbを以下のように編集してください

app/views/tweets/index.html.erb

<div class="contents row">
  <% @tweets.each do |tweet| %>
    <div class="content_post" style="background-image: url(<%= tweet.image %>);">
      <% if user_signed_in? && tweet.user_id == current_user.id %>
        <div class="more">
          <span><%= image_tag 'arrow_top.png' %></span>
          <ul class="more_list">
            <li>
              <%= link_to '編集', "/tweets/#{tweet.id}/edit", method: :get %>
            </li>
            <li>
              <%= link_to '削除', "/tweets/#{tweet.id}", method: :delete %>
            </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>
  <% end %>
  <%= paginate(@tweets) %>
</div>

3.editアクションをコントローラに定義する

ツイートを編集する画面を表示する際にはtweetsコントローラのeditアクションを使用する。
そこで、コントローラにeditアクションを作成していく。
現在実装している編集して更新、という流れは、入力して新規投稿、という流れと似ている。

新規作成時と違うのは、編集→更新の場合は既に存在しているレコードを選択して中身を書き換えるという点である。
そのため、editアクションでは編集したいレコードを@tweetに代入し、編集画面で利用できるようにする。

app/controllers/tweets_controllerを以下のように編集する

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

  def edit
    @tweet = Tweet.find(params[:id])
  end

  private
  def tweet_params
    params.permit(:image, :text)
  end

  def move_to_index
    redirect_to action: :index unless user_signed_in?
  end
end

4.編集画面のビューファイルを作成する

ルーティングとコントローラの編集が終わったので、ビューファイルを作成する。

このビューはツイートを編集するためのビューファイルである。
そのため、ツイートの投稿画面と同様に情報を入力するためのフォームが必要になる。
入力情報の送信先/tweets/編集するツイートのidとなる。
また、情報を送信する際にはpatchというHTTPメソッドを使用する。

patchメソッド

HTTPリクエストにはget、post、deleteメソッドがあることは学習した。
patchメソッドは情報の更新を行う際に使用する。
今回はツイート情報を更新する機能を実装するため、patchメソッドを使用する。

HTTPリクエス

これまでに4種類のHTTPリクエストのメソッドについて学習した。
Railsではこれら4つのメソッドを利用して開発を行う。
役割や機能を以下の表にまとめたので再度確認する。

メソッド 役割
get サーバーからブラウザに情報を返す。単にウェブサイトを閲覧する際にはこのメソッドが利用されている。
post ブラウザからサーバーに情報を送信し、サーバーに情報を保存する。情報の登録などの際に、サーバーに情報を送信するために利用される。
delete ブラウザからサーバーに情報を送信し、サーバーの情報を削除する。アカウントの削除などの際に、サーバー内のデータを削除するために利用される。
patch ブラウザからサーバーに情報を送信し、サーバー内の情報を置き換える。登録情報の更新などの際に、サーバー内のデータを更新するために利用される。
put メソッド名は違うが、patchと同じ役割を持っている。rails3まではputを使っていたが、rails4からはpatchに移行したためカリキュラム内では使用しない。

フォームを作成する際にはフォームの初期値として、編集前のツイート情報を表示する。

以下の指示に従い、app/views/tweets/edit.html.erbを作成する

①ファイルの新規作成

app/views/tweetsディレクトリの中にedit.html.erbというファイルを作成する

②ファイルの編集

問題1:編集画面を作成しましょう

作業ファイル:app/views/tweets/edit.html.erb
ヒント1:下記の例をもとに編集画面を作成しましょう。
ヒント2:このビューでは、コントローラで定義した@tweetを利用できます。@tweetには、編集したいレコードが代入されています。
ヒント3:form_tagメソッドのあたりは、tweetsのnewアクションのビューを参考にしましょう。
ヒント4:編集前の値を表示するには、タグを利用する必要があります。
【例】
edit.html.erb
<div class="contents row">
  form_tagメソッドを使って「/tweets/編集するツイートのid」に「patch」メソッドで情報を送信
    <h3>
      編集する
    </h3>
    <input type="text" name="image" value=編集前の初期値を表示 placeholder="Image Url" autofocus="true">
    <textarea name="text" placeholder="text" rows="10" cols="30">編集前の初期値を表示</textarea>
    <input type="submit" value="SENT">
  <% end %>
</div>

 【 問題1の解答を確認する 】 

5.ツイートの更新を行うためのルーティングを設定する

ツイートの編集画面を作成することができたので、続いてツイートの更新機能を実装していく。

まずはツイートの更新を行うためのルーティングを設定していく。
ツイートを更新する際には/tweets/編集するツイートのidにpatchメソッドでアクセスする。
このパスにアクセスした際にtweetsコントローラのupdateアクションが動くようにする。

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'
  patch   'tweets/:id'  => 'tweets#update'
  get   'tweets/:id/edit'  => 'tweets#edit'
  get   'users/:id'  =>  'users#show'
end

6.updateアクションをコントローラに定義する

ツイートを更新する際にはtweetsコントローラのupdateアクションを使用する。
updateアクション内ではActiveRecordメソッドのupdateを使用する。

updateメソッド

updateはActiveRecordメソッドのうちの一つである。
updateメソッドはモデルのインスタンスに対して使用することで、引数内の情報にレコードを更新することができる。

【例】
コンソール

[1] pry(main)> tweet = Tweet.create(user_id: 1, text: "Hello", image: "test.jpg")
=> #<Tweet id: 1, user_id: 1, text: "Hello", image: "test.jpg", created_at: "2014-12-10 00:00:00", updated_at: "2014-12-10 00:00:00">
[2] pry(main)> tweet.update(text: "Thank you!")
=> true
[3] pry(main)> tweet
=> #<Tweet id: 1, user_id: 1, text: "Thank you!", image: "test.jpg", created_at: "2014-12-10 00:00:00", updated_at: "2014-12-10 00:01:00">

updateメソッドの引数は、update(カラム名: 更新する情報)という形で指定する。
同時に複数の情報を更新する場合にはupdate(カラム1: 更新情報1, カラム2: 更新情報2)という形で使用することができる。
createメソッドと似ている。

 問題2:updateアクションを実装しましょう

作業ファイル:app/controllers/tweets_controller
ヒント1:destroyアクションの実装の時と同じような流れです。
ヒント2:ツイートを更新する際にはActiveRecordメソッドのupdateメソッドを使用しましょう。また、updateメソッドの引数にはtweet_paramsを使用しましょう。

 【 問題2の解答を確認する 】 

7.更新後のビューファイルを追加する

ルーティングとコントローラの編集が終わったので、続いてビューファイルの追加を行う。

このビューファイルはツイートの更新を行ったあとに呼び出されるビューファイルになる。

以下の指示に従い、app/views/tweets/update.html.erbを作成する。

①ファイルの新規作成

app/views/tweetsディレクトリの中にupdate.html.erbというファイルを作成する。

新規作成されるファイル

・app/views/tweets/update.html.erb

②ファイルの編集作成したファイルを、以下のように編集する。app/views/tweets/update.html.erb

<div class="contents row">
  <div class="success">
    <h3>
      更新が完了しました。
    </h3>
    <a class="btn" href="/">投稿一覧へ戻る</a>
  </div>
</div>
トップページを開き、編集機能を試す

① ログインする。

② ツイートを投稿する。

③ ②で投稿したツイートは一番上にある。
そのツイートの編集ボタンをクリックする。

https://tech-master.s3.amazonaws.com/uploads/curriculums//44aed8bf17e4487569df22165ac0e7f2.png

④ 編集画面が表示されるので、テキストを変更する。

https://tech-master.s3.amazonaws.com/uploads/curriculums//03ce16cf4df3381d572b868b8a6495d0.png

⑤ 更新完了画面が表示される。

https://tech-master.s3.amazonaws.com/uploads/curriculums//5093c36f201eab0a182668a7aabba6a9.png

⑥ トップページに戻り、一番上のツイートのテキストが変更されていることを確認する。

https://tech-master.s3.amazonaws.com/uploads/curriculums//ba74794febab9b16a02b06583921eace.png

⑦ これで編集機能実装は完了である。

要点チェック