##はじめに
Railsの学習のアウトプットとして簡単な掲示板を作成している際に、「データの紐付け」にて躓いたので
「紐付け」を行う目的とその手順について、自分用にまとめてみようと思います!
※「ログイン機能」が実装してある事を前提に解説していきます。
##紐付けとは何ぞや
テーブル同士を関連付ける事で、テーブル同士でデータを取得できるようにする作業。
##紐付けをする目的
掲示板作成を例として、上述した二つのテーブルを
・「投稿用のテーブル(postsテーブル)」
・「ユーザーのテーブル(usersテーブル)」
に置き換えることにする。
例えば
投稿テーブルには、**投稿内容のデータ(カラム名をcontentとする)が保存され
ユーザーテーブルには、ユーザーの名前のデータ(カラム名をnameとする)**が保存されているとします。
そうすると以下のように表せます。
postsテーブル
id | content |
---|---|
1 | タピオカなう! |
2 | 学校めんどい…… |
usersテーブル
id | name |
---|---|
1 | 田中 |
2 | 鈴木 |
しかしながら上記2つのテーブルは別物であるため
投稿内容を見ただけでは、誰がどんな投稿したのかという判別がつきません。
そうなると今度は、誰がその投稿をしたのかわかるようにさせたい訳です。
要するにデータの紐付けを行う目的とはこの例で言えば
誰がどの投稿をしたのかを区別することになります。
##紐付けを行う手順
それでは早速、掲示板作成を例として実際に紐付けを行ってみます。
しかし、いきなり紐付けしようとしても、何をどうすれば良いのかサッパリだと思いますから
何をどうしたら良いのか、その思考手順を挙げつつ実装を行っていきます。
####1.まず、実装したい機能を挙げてみる
➡︎投稿ごとにユーザーを区別したい。
####2.その機能を明確にしてみる
➡︎投稿ごとに、誰がその投稿をしたのかわかるように、ユーザー名を表示させる。
####3.Railsにおけるデータのやり取りの仕組みを思い出す
➡︎ブラウザで何かしらの情報を表示させるためには、該当のアクション内で、データベースからデータを取得するための記述をする必要がある。
➡︎今回は「投稿に対して」、その投稿を行った「ユーザーの情報を」表示させたいので、投稿用のアクション内で、ユーザーのデータを取得すればいい。
例
def #(投稿表示用のアクション名)
@post = Post.find_by(id: params[:id])
#ユーザーのデータを取得する処理
end
####4.ユーザーのデータを取得する(?)
➡︎それでは早速、ユーザーのデータを取得してみます。
例
def #(投稿表示用のアクション名)
@post = Post.find_by(id: params[:id])
@user = User.find_by(id: @post.X) #ユーザーのデータを取得する処理
end
➡︎「X」って何だよ…と思ったかと思いますが、何者でもない仮のXだと思ってください。
➡︎何故仮のXを置いているかと言うと、今のままだと
Userモデルのidと一致可能な、Postモデルのデータが存在しないためです。
➡︎なのでこのXの部分に入れるためのカラムを、新しくpostsテーブルに作成する必要があります。こうして紐付けが始まります!
####5.postsテーブルにカラムを追加
➡︎「Userモデルのidと一致させるためのid」と言う意味で、「user_id」と言うカラム名にします。
➡︎新しくカラムを追加するためには、「rails g migration」コマンドを実行してあげる必要があります。
➡︎今回はuser_idカラムを、Postモデルに追加するので、以下のようにコマンドを実行します
$ rails g migration AddUserIdToPost user_id:integer
➡︎「db/migrate」ディレクトリ内に、「(作成した日付の数字羅列)add_user_id_to_post.rb」ファイルが追加されている事を確認。
➡︎これで、Railsのアプリケーションフォルダ内にはファイルが作成されたので、この変更をデータベースに反映させます。
$ rails db:migrate
➡︎上記のようにコマンドを実行したら、ターミナルで「rails dbconsole」コマンドを実行して、postsテーブルに「user_id」カラムが追加されている事を確認してください。
postsテーブル
id | content | user_id |
---|---|---|
1 | タピオカなう! | |
2 | 学校めんどい…… |
####6.user_idカラムに、ユーザーのidを取得させる
➡︎もう一度、先ほどの投稿表示用のアクションを確認してみます。
def #(投稿表示用のアクション名)
@post = Post.find_by(id: params[:id])
@user = User.find_by(id: @post.user_id) #ユーザーのデータを取得する処理
end
➡︎新たにカラムを作成したので、仮のXを「user_id」に変更しました。
➡︎ただし、まだこのままではuser_idカラムは空のままなので、参照するためのidがありません。
➡︎なので今から、user_idカラムに、その投稿をしたユーザーのidを取得させるための記述を行ます。
➡︎どうやって取得させるかと言うと、新規投稿アクション内の、newメソッドの引数にuser_idを渡し、user_idに「ログインしているユーザーのid」が保存されるようにします。
例
def #(新規投稿アクション名)
@post = Post.new(
content: params[:content],
user_id: @current_user.id #ログインユーザーのidを取得して保存
)
#新規投稿保存後の処理
end
➡︎これにより、これ以降に新規投稿が行われる度に、ログインしているユーザーのidが保存されるようになります。
postsテーブル
id | content | user_id |
---|---|---|
1 | タピオカなう! | |
2 | 学校めんどい…… | |
3 | 納豆好き | @current_user.id |
4 | ポンポンポン | @current_user.id |
➡︎idが1のユーザーが新規投稿を行えば、その投稿のuser_idには1が入るし、2のユーザーが新規投稿を行えば2が入ります。
➡︎これで、ユーザーのidを取得させることができました。
####7.ビューで表示
➡︎新規投稿するごとにログインユーザーのidが取得されるため、以下のように呼び出すと、「その投稿を行ったユーザーのid」と一致する「Userモデル内のid」を検索して取得してくれるようになります。
def #(投稿表示用のアクション名)
@post = Post.find_by(id: params[:id])
@user = User.find_by(id: @post.user_id) #ユーザーのデータを取得する処理
end
➡︎これにより紐付けは完了したので、投稿詳細ページで表示していきます。
<%= @user.name %>
<%= @post.content %>
➡︎後はこれにCSSなどでスタイリングしてあげれば、投稿に対してユーザー名を表示できるようになるかと思います!
##補足にもならない補足
本来ならば投稿詳細ページにだけでなく、別のページの投稿に対してもユーザーの情報を紐付けする必要があると思います。
そうした場合、他のアクションでユーザーの情報を取得する記述をすることになるため、重複することになります。
同じ記述をするのは好ましくないため、ユーザーの情報を一挙に取得するためのメソッド(インスタンスメソッド)を定義する必要があるのですが
インスタンスメソッドに関する解説は、また次回したいと思います。
##まとめ
最後に、投稿とユーザーについての紐付けを行う手順をもう一度確認してみましょう。
####1.まず、実装したい機能を挙げてみる
####2.その機能を明確にしてみる
####3.Railsにおけるデータのやり取りの仕組みを思い出す
####4.該当アクション内に、ユーザーのデータを取得する処理を記述してみる(仮)
####5.postsテーブルにカラムを追加
####6.user_idカラムに、ユーザーのidを取得させる
####7.ビューで表示
です!
##最後に
Railsにつきましては、学習を始めて2週間の初学者も初学者ですので
Railsにおけるデータのやり取りについて慣れることが先決と考え、このように遠回りするような理解の仕方を取っています。
おかしな点などありましたら、その都度仰って頂けるととても幸いです。