自分の手で未来を創るーlav0

自分のために、誰かのために、今ここにないもの、もっと良くしたいもの、何でも自分の手で創っていく。そして、作ったものを公開していきます

Rails 6.0でアプリを開発 基本の流れ⑨ 情報の更新や削除

今回はユーザー情報の更新や削除の機能、管理者の機能を実装するためのメモ

f:id:kslabo51:20200306225201j:plain

 

実現したいこと

 

ユーザー情報を更新できるのはそのユーザー自身。そのすみわけと、ユーザーを削除できるのは管理者のみ。という機能の実装。

 

1)ユーザー情報の更新

ユーザー情報をそのユーザー自身のみ更新できるようにするには、承認機構とbeforeフィルタを使って実装する。

 

①Usersコントローラーにeditアクションを追加。

params[:id]でそのユーザーのIDを見つける。

f:id:kslabo51:20200306195817p:plain

 

②editアクションに対応するviewの作成

編集の項目を作る。

f:id:kslabo51:20200306202453p:plain

 

※仕組み補足

f:id:kslabo51:20200306203300p:plain

 

③headerのリンクを更新

この時current_userヘルパーメソッドを使用することで現在ユーザーの編集画面に移行

 

f:id:kslabo51:20200306203411p:plain

 

④newとeditの共通部分をパーシャル化する

ⅰ)パーシャルの作成

form_for部分をパーシャルにまとめる

ボタン内の文言は実際のページからprovideで送りyieldで受け取る

f:id:kslabo51:20200306204845p:plain

 

ⅱ)新規登録フォームからフォーム部分を抜く

ボタン内の文言を送る

renderでフォーム部分を表示

f:id:kslabo51:20200306205117p:plain

 

ⅲ)編集フォームからフォーム部分を抜く

ボタン内の文言を送る

renderでフォーム部分を表示

f:id:kslabo51:20200306205319p:plain

 

⑤updateアクションの作成

更新はupdate_attribute(user_params)を使用。

条件付きで成功時と失敗時の挙動を記述。

f:id:kslabo51:20200306205826p:plain

 

2)統合テストでチェック

$ rails g integration_test users_edit

 

①編集に失敗するテスト

エラー時の表示もテスト

f:id:kslabo51:20200306213003p:plain

 

エラー情報

DEPRECATION WARNING: update_attributes is deprecated and will be removed from Rails 6.1 (please, use update instead)

update_attributesがupdateに代わります

f:id:kslabo51:20200306212603p:plain

これでエラーは出なくなった

 

②編集に成功するテスト

f:id:kslabo51:20200306215251p:plain

駆動開発として上記がパスするように設定

 

ⅰ)updateアクションにフラッシュメッセージを入れ、ユーザーページにリダイレクトさせる。

f:id:kslabo51:20200306214147p:plain

 

ⅱ)パスワードを更新しなくてもいいように空だった時に例外処理を入れる。

f:id:kslabo51:20200306214425p:plain

allow_nil: true

※新規登録時はhas_secure_passwordでオブジェクト生成時に存在性を検証しているため問題なし

 

3)認証と認可

認証 サイトのユーザーを識別する(authentication)

認可 そのユーザーが実行可能な操作を管理(authorizaiton)

 

編集ではユーザーにログインを要求かつ、自分以外のユーザー情報を更新できないように制御する必要あり

・ログインしていないユーザーからの保護として

→ログインページへ転送+メッセージを表示

・ログイン済みだが許可されていないページへアクセスしようとすることから保護

→ルートへリダイレクト

 

①beforeフィルターと対応するメソッドを作成し、onlyオプションで適用範囲を制限

f:id:kslabo51:20200306221042p:plain

f:id:kslabo51:20200306221053p:plain

この変更に伴い、users_edit_testの両テストで最初にログインしておくように設定しなおしておく。(log_in_asを使用)

f:id:kslabo51:20200306221402p:plain

 

②ログインしていないユーザーがリダイレクトさせられるかチェックするテスト

f:id:kslabo51:20200306222327p:plain

 

③自分以外の情報を編集できないようにする

ⅰ)fixtureファイルに二人目のユーザーを追加

f:id:kslabo51:20200306223120p:plain

ⅱ)テストに二人目のユーザーを追加し間違ったユーザーが編集しようとしたときのテストを追加とbeforeフィルターと対応メソッドを作成

f:id:kslabo51:20200306223535p:plain

beforeフィルターをかけ、正しいユーザーかどうか確認させる

f:id:kslabo51:20200306224112p:plain

f:id:kslabo51:20200306224121p:plain

ⅲ)current_user?(user)ヘルパーメソッドを作成

f:id:kslabo51:20200306224531p:plain

ⅳ)ヘルパーメソッドを使ってcorrect_userメソッドを書き換え

f:id:kslabo51:20200306224902p:plain

 

4)フレンドリーフォーワーディング

ログインしていないユーザーがログインページへ飛ばされた後、ログインしなおした際にもともと入ろうとしたページに飛ばす

 

①フレンドリーフォーワーディングのテスト

f:id:kslabo51:20200307102526p:plain

 

②フレンドリーフォーワーディングの実装

ⅰ)session_helper.rbに下記メソッドを作成

store_locationメソッド

 リクエスト時のページを保存するメソッド

redirect_back_orメソッド

 その場所にリダイレクトさせるメソッド

f:id:kslabo51:20200307110342p:plain

※ブラウザに記憶させるのでsession変数を使用

※Getリクエストを送られたURLをsessionのforwarding_urlに保存

 

ⅱ)ログインユーザー用beforeフィルターにstore_locationを追加

f:id:kslabo51:20200307103617p:plain

 

ⅲ)ログインのcreateアクションにフレンドリーフォーワーディング機能実装

f:id:kslabo51:20200307103908p:plain

 

ⅳ)session上に保存したurlが削除されフレンドリーフォーワーディングが有効なのは一度だけになっているかテスト

f:id:kslabo51:20200307104445p:plain

 

4)ユーザー一覧ページの作成

indexで表示。ログインしたユーザーにしか見えないようにする。

 

①ログインしていないユーザーがアクセスしたときに、indexアクションにリダイレクトするかテスト

f:id:kslabo51:20200307105334p:plain

 

②indexアクションにログインを要求する

・beforeフィルター(logged_in_user)にindexアクションを追加

・indexアクションを作成

・すべてのユーザーを表示させる変数を作成

f:id:kslabo51:20200307110905p:plain

 

③indexビューの作成(ユーザーの一覧ページ)

f:id:kslabo51:20200307112800p:plain

 

④スタイルの編集

f:id:kslabo51:20200307111837p:plain

 

⑤トップページのリンクを全部テストでチェックしてみる

f:id:kslabo51:20200307113918p:plain

 

5)サンプルユーザーを追加する

①サンプルユーザーを使用するために、GemfileにFaker gemを追加する

f:id:kslabo51:20200307114341p:plain

※bundle install

 

②seedsファイルでサンプルユーザーを生成する

f:id:kslabo51:20200307115010p:plain

 

③DBないのデータをいったんリセットしSeeds内のデータを追加

$ rails db:migrate:reset

$ rails db:seed

※エラーが出た場合、それに従う

 

6)ページネーション

①Gemfileにkaminariを追加

f:id:kslabo51:20200307225546p:plain

※bundle install

 

②viewでページネーションを行うようにRailsに指示

f:id:kslabo51:20200307225801p:plain

 

③indexアクションをページネーション用に編集

・allをpageメソッドに

・:pageパラメーターに使われるparams[:page]はkaminariによって自動的に生成

f:id:kslabo51:20200307225947p:plain

 

④テスト用にfixtureに30人ユーザーを追加する

f:id:kslabo51:20200308122150p:plain

 

⑤統合テストファイルを作成する

$ rails g integration_test users_index

f:id:kslabo51:20200308123250p:plain

 

7)リファクタリング

①index.html.erbでユーザー一覧のliタグをrender呼び出しに変更

f:id:kslabo51:20200308123605p:plain

この部分を、

f:id:kslabo51:20200308123846p:plain

こうする。renderをパーシャルではなくてUserクラスのuser変数に対して行う。

自動的に_user.html.erbを探しに行く

 

②_user.html.erbパーシャルを作成

f:id:kslabo51:20200308124147p:plain

 

③さらにリファクタリング

f:id:kslabo51:20200308123846p:plain

この部分を、

f:id:kslabo51:20200308124550p:plain

インスタンス変数に対してrenderを直接実行するようにする。

自動的に@usersをUserオブジェクトのリストと推測してくれ、それぞれのユーザーを列挙し出力してくれる。

 

8)管理ユーザーの作成

①admin属性をUserモデルに追加

$ rails g migration add_admin_to_users admin:boolean

 

②デフォルトでは管理者になれないようにする

default: falseを追加で記述

f:id:kslabo51:20200308125257p:plain

$ rails db:migrate

 

③seedファイルで最初のユーザーを管理者にする

f:id:kslabo51:20200308125659p:plain

 

④DBをリセットしサンプルデータを再度生成する

$ rails db:migrate:reset

$ rails db:seed

 

⑤admin属性の変換が禁止されていることをテスト

StrongParametersにadminが入っていないのでadminは更新されない。

f:id:kslabo51:20200308134727p:plain

9)ユーザーの削除

①indexページにユーザー削除用のリンクを追加。

f:id:kslabo51:20200308135509p:plain

リンクの生成を行っているのは method: :deleteの部分。

条件分岐でadminユーザーのみに削除リンクを表示させるようにする。

 

②destroyアクションの追加

f:id:kslabo51:20200308140226p:plain

・destroyアクションもログインを要するbeforeフィルターで追加

f:id:kslabo51:20200308140312p:plain

・admin_userメソッドとbeforeフィルターを設置し管理者だけに限定

f:id:kslabo51:20200308140451p:plain

 

③ユーザー削除のテスト

ⅰ)fixture内の一人を管理者に

f:id:kslabo51:20200308140709p:plain

 

ⅱ)管理者権限の制御をテスト(コントローラー)

・ログインしなければ削除できない

・管理者でなければ削除できない

f:id:kslabo51:20200308141249p:plain

 

ⅲ)indexページで削除リンクとユーザー削除に対する統合テスト

f:id:kslabo51:20200308142114p:plain

 

長かったがここまでで情報更新、削除、管理者の設定が完了

 

参考にさせていただいたサイト

第10章 ユーザーの更新・表示・削除 - Railsチュートリアル

Ruby on Rails チュートリアル 第10章 ユーザー更新 beforeフィルター フレンドリーフォワーディング adminまで - Qiita