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

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

Rails 6.0でアプリを開発 基本の流れ⑫ 記事投稿の設定

今回はユーザーが記事を投稿する機能実装のメモ

f:id:kslabo51:20200314133255j:plain

 実現したいこと

userが短い記事、画像、および動画を投稿できるようにする

 

1)Postモデルの生成

①Postモデルが持つ属性は

 

 content(text)

user_id(integer)

created_at(datetime)

updated_at(datetime)

 

②モデルの生成

$ rails g model Post content:text user:references

 

③インデックスが付与されたMicropostのマイグレーション

f:id:kslabo51:20200313205019p:plain

※インデックスと外部キー参照付きのuser_idカラムが追加、また[:user_id, :created_at]と1つの配列に入れることで両方のキーを同時に扱う複合インデックスを作成

 

f:id:kslabo51:20200313204545p:plain

※user:referencesでbelongs_to:userが追加される

 

マイグレーション

$ rails db:migrate

 

2)バリデーションの追加

①記事の有効性に対するテスト

f:id:kslabo51:20200313210259p:plain

 

②user_idに対する検証

f:id:kslabo51:20200313210622p:plain

 

③記事のバリデーションに対するテスト

f:id:kslabo51:20200313210910p:plain

 

④③に対してのバリデーション

f:id:kslabo51:20200313211101p:plain

 

3)記事とユーザーを紐づける

  • belongs_toはすでに自動生成済み。
  • has_manyをUserモデル側に設定

f:id:kslabo51:20200313211338p:plain

※userは複数のpostを持ち、postは一人のuserを持つ

 

4)2)-①のset upメソッドを修正

new → buildへ(buildはuserに紐づいた新しいPostオブジェクトを返す)

f:id:kslabo51:20200313211529p:plain

 

5)記事の順序付けを行う

①テストを記述

f:id:kslabo51:20200313212257p:plain

 

②記事のfixtureの作成

f:id:kslabo51:20200313212727p:plain

 

③記事を順序付ける(新しいもの順)

  • default_scopeメソッド=DBから要素を取得した際のデフォルトの順序を指定するメソッド
  • DESC=降順
  • 記述はラムダ式

f:id:kslabo51:20200313212852p:plain

 

6)ユーザー破棄で関連記事も破棄されるようにする

①記事がその所有者と一緒に破棄されることを保証する

f:id:kslabo51:20200313213221p:plain

 

②破棄されるかモデルのテストでチェック

f:id:kslabo51:20200313213935p:plain

 

7)ここまでで記事をいくつか作成している場合リセット

$ rails db:migrate:reset

$ rails db:seed

 

8)Postコントローラーの作成

$ rails g controller Posts

 

9)記事を表示するパーシャルを作成(1つの記事)

f:id:kslabo51:20200314120359p:plain
 

10)記事のインスタンス変数を定義

paginateを使用する

f:id:kslabo51:20200313215735p:plain

 

11)showページに記事を表示

順序が必要なのでolタグを使用

f:id:kslabo51:20200313223202p:plain

 

12)サンプルデータに記事を追加

f:id:kslabo51:20200313223256p:plain

 

13)サンプルデータを再度作成

$ rails db:migrate:reset

$ rails db:seed

 

14)記事にスタイルを与える

f:id:kslabo51:20200313224536p:plain

f:id:kslabo51:20200313224654p:plain

15)プロフ画面の記事に対する統合テスト

①テストの作成

$ rails g integration_test users_profile

 

②記事のfixtureをユーザーに関連付ける

f:id:kslabo51:20200314093736p:plain

 

③ユーザーのプロフ画面に対するテスト

f:id:kslabo51:20200314102359p:plain

 

※ここでテストを実行するとターミナルで下記のような文言

To automatically update from positional arguments to keyword arguments,
install rubocop-faker and run:

rubocop \
--require rubocop-faker \
--only Faker/DeprecatedArguments \
--auto-correct

 

こちらのサイトを参考にさせていただきgemをインストール

RuboCop is 何? - Qiita

 

上記消えないので、ターミナルの指示通り

$ gem i rubocop-faker

を実行

 

でも消えないので、指示通りに

$rubocop --require rubocop-faker --only Faker/DeprecatedArguments --auto-correct

を実行

f:id:kslabo51:20200314101537p:plain

ターミナルが動き出し自動修正?

f:id:kslabo51:20200314101603p:plain

確かに自動的に変更されている!!

 

もう一度テストを実行すると再度表示が出てくる。表示を見ると

Passing `word_count` with the 1st argument of `sentence` is deprecated. Use keyword argument like `sentence(word_count: ...)` instead.

 

一応もう一度

$rubocop --require rubocop-faker --only Faker/DeprecatedArguments --auto-correct

を実行

f:id:kslabo51:20200314102547p:plain

違反は何もないみたい。

 

今回使っているposts.yml内にLorem.sentenceがあるので、ここもseed同様変更

f:id:kslabo51:20200314102211p:plain

その後テストを実行するとメッセージは出ずGreenに!! 

 

16)Postリソースのルーティング設定

記事は主にプロフページとトップページのコントローラーを実行されるのでnewやeditアクションは不要。createとdestroyがあればよい

f:id:kslabo51:20200314102958p:plain

 

17)アクセス制御の設定

関連付けられたユーザーを通して記事にアクセスするのでcreate、destroyアクションはログイン済みであること

 

①Postコントローラーの認可テスト

f:id:kslabo51:20200314105226p:plain

 

②logged_in_userメソッドをApplicationコントローラーに移動。ログイン要求のメソッドはPostコントローラーでも必要になるのでどこからでも使えるApplicationコントローラーにUserコントローラーから移動。

f:id:kslabo51:20200314104521p:plain

※userコントローラーのlogged_in_userは削除

 

③createとdestroyアクションに対して認可を追加

 

f:id:kslabo51:20200314104800p:plain

 

18)記事用のフォームを生成

micropost/newページを使わずにホーム画面に置く

 

①Postコントローラーのcreateアクションの設定

※ストロングパラメータも設定

f:id:kslabo51:20200314105858p:plain

 

②ホームにPostの投稿フォームを追加

f:id:kslabo51:20200314110543p:plain

 

③サイドバーで表示するユーザー情報のパーシャル

f:id:kslabo51:20200314112609p:plain
 

④記事投稿用のパーシャル

f:id:kslabo51:20200314112649p:plain

 

⑤トップページ画面に記事のインスタンス変数を置く

※フォームをトップページに置くため

f:id:kslabo51:20200314112742p:plain

 

⑥Userオブジェクト以外でも動作するようにerror_messagesパーシャルを更新

f:id:kslabo51:20200314112905p:plain

 

⑦ユーザー登録時、ユーザー編集時、パスワード再設定時のエラー表示を更新

※⑥による変更で2つのページを更新

※ユーザー登録時とユーザー編集時はパーシャルにしているのでパーシャルを編集

f:id:kslabo51:20200314113308p:plain

 

f:id:kslabo51:20200314113353p:plain

 

19)feedメソッドの作成

全てのユーザーがfeedを持つのでUserモデルに作成

①現在ログインしているユーザーの記事をすべて取得してくる

 

f:id:kslabo51:20200314113838p:plain

"user_id = ?" →SQLクエリに代入する前にidがエスケープされSQLインジェクションと呼ばれセキュリティホールを避ける。

SQLに変数を代入する場合、常にエスケープする癖をつける)

 

②homeアクションにフィードのインスタンス変数を追加

f:id:kslabo51:20200314114202p:plain

 

③ステータスフィードのパーシャルを作成

f:id:kslabo51:20200314114502p:plain

railsは対応する名前のパーシャルを渡されたリソースのディレクトリから探しに行ける。

@feed_item → Micropostのパーシャル

@micropost → Micropostのパーシャル

@user → Userのパーシャル

 

④トップページにステータスフィードを追加 

f:id:kslabo51:20200314120811p:plain

 

⑤createアクションに空の@feed_itemsのインスタンス変数を追加

f:id:kslabo51:20200314121146p:plain

※投稿が失敗しても崩れないようにするため

 

20)記事の削除

投稿したユーザーのみ削除リンクが動作するようにする

 

①記事のパーシャルに削除リンクを追加

f:id:kslabo51:20200314121918p:plain

 

②Postコントローラーにdestroyアクションを定義

f:id:kslabo51:20200314125011p:plain

 

③Postコントローラーにbeforeコールバックを設定

current_userのみがdestroyできる 

f:id:kslabo51:20200314124902p:plain

f:id:kslabo51:20200314125105p:plain

request.refererメソッド

 フレンドリーフォーワーディングのrequest.urlに似ていて一つ前のurlを返す

(=redirect_back(fallback_location: root_url)

 

21)feed画面の記事をテストする

①記事用fixtureに別のユーザーに所属している記事を追加

f:id:kslabo51:20200314125807p:plain
 

②間違ったユーザーによる記事削除に対するテスト

f:id:kslabo51:20200314130131p:plain

 

③統合テスト

ⅰ)統合テストの生成

$ rails g integration_test posts_interface

 

ⅱ)UIに対する統合テスト

f:id:kslabo51:20200314132036p:plain

f:id:kslabo51:20200314132046p:plain

 

ⅲ)再度バーで記事の投稿数をテストするためのテンプレ

f:id:kslabo51:20200314132850p:plain

 

22)画像を投稿する

Postモデルに複数の画像ファイルを紐づける形で

 

 

・・画像フォーマットのバリデーション

・・画像に対するバリデーション

・・動画の投稿

・・テスト

 

今回はとても長いので画像投稿は別途まとめる(^^)/

 

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

第13章 ユーザーのマイクロポスト - Railsチュートリアル

RuboCop is 何? - Qiita

RuboCop Faker を作った - koicの日記