#はじめに
こんにちは!DMM WEBCAMP Advent Calendar 2021 16日目担当の@naoyuki0920です。
今回は日ごろメンターとして質問対応をしていく中で、質問の多いポイントがいくつかありましたので、メンター視点で書いていきたいと思います。もしかしたら、皆さんが実装している方法とは異なる部分もあるかもしれませんが、こんな方法もあるんだー程度でぜひ参考にしてみてください。
それではレッツゴー!!
#目次
- つまずきレベル1
- renderとredirect_to
- MVCとは?
- つまずきレベル2
- form_withで指定するmodelとは?
- eachメソッドについてもっと詳しく
- つまずきレベル3
- フォロー・フォロワー機能の仕組み
- さいごに
#つまずきレベル1 ★☆☆
まずはRailsを学習し始めて最初につまずきがちなポイントです!
###render と redirect_to
まず初めにrenderとredirect_toをチョイスしました。この違い、皆さんきちんと理解できておりますでしょうか?他人に自分の言葉で説明できますか?ちょっと怪しいと思ったそこのあなた!復習のチャンスです!
一言で違いを言うならば、コントローラーを新たに呼び出すか、呼び出さないかです。
renderはrenderを記述したコントローラを使ってrender先のViewを表示する
ridirect_toは、指定したパスが示すコントローラーのアクションを起動し、Viewを表示する
言葉で説明するとこんな感じです。わかりやすいように図を載せます。
いかがでしょうか?イメージわきましたか?今ははっきりイメージできなくても、使い分けていくうちにそれぞれの特徴をつかめると思います。renderとredirect_toはそれぞれ、指定するものや記述方法、使う際の注意点などがいろいろありますので、詳しくはrender redirect_to 違い
などで調べてよりわかりやすい説明を見つけてみましょう!
###MVCとは?
意外と見落としがちなMVCですが、Railsで開発を進めていくうえで必要不可欠です。Railsだけでなく、様々なアプリケーションでMVCを基本とした開発が行われています。これを機に復習しましょう!
MVCとはモデル(Model)、ビュー(View)、コントローラー(Controller)の頭文字をとった言葉です。アプリケーションでは様々なデータを扱うと同時に、ユーザーの操作に合わせたアクションを行います。これらの管理をするための司令塔の代表みたいなものです。三権分立(立法権、行政権、司法権)に少し似ていますね。
これも先ほどと同様図を載せて説明しますね。
どうでしょうか視覚的にイメージできましたか?目に見える部分と目に見えない部分、その2つをつなぐ部分という役割分担によってアプリケーションは出来上がっているのですね。MVCのほかにもMVPモデルやMVVNなどもありますが、RailsではMVCを使用しています。これからはMVCを意識してデータの動きや変数の受け渡しを考えて実装してみましょう!
#つまずきレベル2 ★★☆
続いて実際にアプリケーションを作成している途中にあれ?ってなりがちなポイントを押さえていきましょう!
###form_withで指定するmodelとは?
意外と見落としがちですよね。きちんと説明できますか?
まず、form_with内のmodelとはモデルオブジェクトのことを指しています。モデルオブジェクトは、form_withを使って新規にデータを投稿したり、データを更新したいテーブルのカラムを指すことが多いです。
新規投稿する際のmodelは
.new
を付けたインスタンス変数
編集する際のmodelは.find(params[:id])
で探索を行ったインスタンス変数
主にこの2つをform_withのmodelに渡します。
form_withを使う目的によってmodelに渡す内容は変化するので、form_withの目的を意識して実装するとわかりやすいです。
このことを意識しておくだけで、form_withを使う際のハードルがぐっと下がるので意識してみましょう!
###eachメソッドについてもっと詳しく
webサイトを作成するときに繰り返し処理を行いたいときありますよね。データベースの情報を複数取得して一覧表示したいときなどによく使います。今一度確認しておきましょう。
eachメソッドを使う際のテンプレートを紹介します。
<% @users.each do |user| %>
<%= user.id %>
<%= user.name %>
<%= user.email %>
<% end %>
こんな感じになりますね。ざっくり流れを見ていきます。
1.usersコントローラーのindexアクション内で定義した
@users
というインスタンス変数をViewが受け取る。
2.受け取ったインスタンス変数の中身をデータベースのレコード単位で取り出し、Viewのeach文内だけで使えるローカル変数user
に代入する。
3.eachメソッドをインスタンス変数が所持しているレコード数だけ繰り返し、Viewとして出力する。
このような流れでViewを表示しています。データの流れを意識しながらコーディングできるようになるとより上達できるかと思います。ぜひ意識してみてください。
#つまずきレベル3 ★★★
ここからはRailsをある程度学習し、よりレベルの高い機能を実装しようとしている方向けです。私も、受講生さんにわかりやすいイメージを伝えるのが難しいなと感じる部分です。では行きましょう!
###フォロー・フォロワー機能の仕組み
昨今のSNSには必ずといっていいほど搭載されている機能ですね。実装の大まかな流れを解説します。またすでにuserモデルやテーブルは存在しているものとして進めます。今回紹介するもの以外の実装方法もたくさんあるのであしからず。
1.ユーザーとユーザーをつなげるためのrelationshipsテーブルとモデルを作成。
2.userモデルとrelationshipsモデルにアソシエーションを記述
3.userモデルにフォロー機能のメソッドを定義する。
4.relationshipsコントローラーの作成、編集
####1. relationshipsモデルの作成
まず初めにuserとuserをつなぐための中間テーブルを作成します。
rails g model relationships
を実行しmigrationファイルを作成し編集しましょう。
migrationファイルは以下の通りです。
class CreateRelationships < ActiveRecord::Migration[5.2]
def change
create_table :relationships do |t|
t.references :user, foreign_key: true
t.references :follow, foreign_key: { to_table: :users }
t.timestamps
t.index [:user_id, :follow_id], unique: true
end
end
end
referencesという見慣れないものが出てきました。これは既に存在しているテーブルを指定する場合に使用します。t.references :user
がさしているのは既存のuserテーブルだということですね。foreign_keyとはデータベースの外部キー制約の事です。詳しい説明は省きますので興味があれば調べてみましょう。
rails db:migrate
の実行を忘れずに!
####2. アソシエーションの設定
続いて先ほど作成したrelationshipsモデルとuserモデルのアソシエーションを設定します。
class Relationship < ApplicationRecord
belongs_to :user
belongs_to :follow, class_name: 'User'
validates :user_id, presence: true
validates :follow_id, presence: true
end
ここで、あれ?となった方。大丈夫です。followモデルは作成していません。belongs_to :follow, class_name: 'User'
について少し補足しますね。class_name: 'User'
とすることで、Userモデルを参照できるようになります。followモデルは実体のない仮想上のモデルというイメージです。
それってbelongs_to :user
と同じじゃない?ってなりますよね。なぜこんな回りくどいやり方をするかについてはもう少し進むとわかります。いったん先に進みますね。
次はuserモデルのリレーションです。
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
# フォローしている人
has_many :relationships
has_many :followings, through: :relationships, source: :follow
# フォロワー
has_many :reverse_of_relationships, class_name: 'Relationship', foreign_key: 'follow_id'
has_many :followers, through: :reverse_of_relationships ,source: :user
end
上の方から順番に行きますね。
まずはフォローの設定から。
has_many :relationships
これは大丈夫ですね。いつも通りのデータベースのリレーションを定義しています。
has_many :followings, through: :relationships, source: :follow
これは少し難しいですね。また見知らぬモデルfollowings
が登場しました。これも先ほどのfollowモデルと同じ存在です。
through: :relationships
は中間テーブルがrelationshipsだよと宣言しています。中間テーブルとはテーブルとテーブルを結ぶためのテーブルの事です。
次にフォロワーの設定です。
has_many :reverse_of_relationships, class_name: 'Relationship', foreign_key: 'follow_id'
うわまたかよ…って思うかもしれないですが、これもたった今新しく作成したモデルです。followとは逆のフォローされる関係になるのでreverse_of_をつけてあるだけです。ただ、勝手にモデルを作ることはできないので、class_name: 'Relationship'
を使ってrelationテーブルを参照するように設定しています。
foreign_key: 'follow_id'
についてですが、これを追加することによって、@user.followings
を使うことができるようになります。
####3. Userモデルでフォロー・アンフォロー機能の設定
次にUserモデルにメソッドを追記していきます。
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
# フォローしている人
has_many :relationships
has_many :followings, through: :relationships, source: :follow
# フォロワー
has_many :reverse_of_relationships, class_name: 'Relationship', foreign_key: 'follow_id'
has_many :followers, through: :reverse_of_relationships ,source: :user
def following?(another_user)
self.followings.include?(another_user)
end
def follow(another_user)
unless self == another_user
self.relationships.find_or_create_by(follow_id: another_user.id)
end
end
def unfollow(another_user)
unless self == another_user
relationship = self.relationships.find_by(follow_id: another_user.id)
relationship.destroy if relationship
end
end
end
こんな感じになります。書き方はいくつもあるので、ご自身が好きな書き方で実装してみてください!
####4. relationshipsコントローラーの作成編集
続いて、コントローラーを作成、編集します。
class RelationshipsController < ApplicationController
before_action :authenticate_user!
def create
@user = User.find(params[:user_id])
current_user.follow(@user)
redirect_to request.referer
end
def destroy
@user = User.find(params[:user_id])
current_user.unfollow(@user)
redirect_to request.referer
end
end
こんな感じになるかと思います。説明は省きますね。
ここまで来たら、あとはViewとrouteを作成するだけです。気合で頑張りましょう。
いかがでしょうか。このような感じで実装すると、フォローフォロワー機能を作成することができます。
やはりポイントになってくるのが、データベースに対する理解ですね。中間テーブルなど、フォローフォロワー機能には複数のデータベースの知識が必要になります。データベースに関する資格があるくらいですので、とても奥が深いです。もし興味があれば、ぜひデータベースについて勉強してみましょう!
#さいごに
ここまで初学者の方が躓きがちなポイントをいくつか紹介してきました。複雑な処理を実装するためにはとても多くの経験と知識が必要になると考えています。皆さんの実装したいアプリケーションにこの記事が少しでも参考になれば幸いです。また、今回紹介しきれなかったものについても、少し調べるとたくさんの記事が見つかるはずです。ぜひ調べて、ともにどんどん成長していきましょう!
それでは最後までお付き合いいただきありがとうございました!あなたのRailsライフが充実することを願っています!!