さらなる高みへ -higher ground -

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

アソシエーションを理解する

ここではアソシエーションについて学習する。
Railsを使う上でとても便利で大事な機能であるため、理解できるまで繰り返し学習が必要である。

アソシエーションを利用する

Railsにはモデル間の関係を管理するアソシエーションという機能がある。
今回の作業ではこのアソシエーションという機能を実装する。

アソシエーション

アソシエーションとはモデル間の関連付けを管理する機能のことで、定義しておくことでモデルをまたいだデータの呼び出しをより簡単に行うことができるようになる。

今回の場合、UserモデルとTweetモデルをアソシエーションで関連付けする。
下のヒントを参考にしながら実装を行う。

作業内容

1.アソシエーションを定義する

2.アソシエーションを実装する

1.アソシエーションを定義する

アソシエーションを利用するために、まずはモデル間の関係を定義する。
アソシエーションを利用するには以下の2つの条件を満たす必要がある。

  1. モデルクラスにhas_manyやbelongs_toなどの定義がされている
  2. 所属する側のテーブルに所属するクラス名_idというカラムがある

②の実装に関してはすで行っているため、これから①の実装に関しての説明を行う。
現在PicTweetにはサインアップという機能があり、利用者がユーザーを作成してログインを行うことができる。
また、ツイートの投稿に関してはログインしたユーザーのみが行うことができる。

つまり、全てのツイートはいずれかのユーザーが作成したものであり、逆に言えばユーザーは自分の作成したツイートを複数個所持している状態といえる。

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

Userモデルの視点で考えると、あるuserの作成したtweetが複数個ある状態と言える。
この状態のことをhas manyの関係といい、今回の場合には「User has many Tweets」の状態であると言える。

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

この関係をアソシエーションで定義するためにはUserモデルのモデルファイルを編集する
「User has many Tweets」の状態を定義するため、Userモデルのモデルファイルにhas_many :tweetsと追記する。

以下の指示に従い、app/models/user.rbを編集する

app/models/tweet.rb

class Tweet < ApplicationRecord belongs_to :user end

また、Tweetモデルの視点で考えると、全てのtweetはいずれかのuserに属している状態と言える。
この状態のことをbelongs toの関係といい、今回の場合は「Tweet belongs to User」の状態であると言える。

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

この関係をアソシエーションで定義するためにはTweetモデルのモデルファイルを編集する。
Tweet belongs to User」の関係を定義するため、Tweetモデルのモデルファイルにbelongs_to :userと追記する。

2.アソシエーションを実装する

この関係をアソシエーションで定義するためにはTweetモデルのモデルファイルを編集する
Tweet belongs to User」の関係を定義するため、Tweetモデルのモデルファイルにbelongs_to :userと追記する。

 

class Tweet < ApplicationRecord
  belongs_to :user
end
以下の指示に従い、app/models/tweet.rbを編集する

app/models/tweet.rb

class Tweet < ApplicationRecord
  belongs_to :user
end

2.アソシエーションを実装する

以上の作業でアソシエーションを定義することができた。
そこで、実際にアソシエーションを利用して実装を行っていく。
さきほど編集を行ったusers_controller.rbshowアクション部分でのデータの呼び出しにアソシエーションを使用して記述を行う。

アソシエーションを定義すると、モデルをまたいだデータの呼び出しをより直感的に行うことができる。
便利さを実感するため、アソシエーションを使用しない場合とする場合のコードの違いを見てみまる。

アソシエーションを使用しない場合は、以下のように現在ログイン中のユーザーが投稿したツイートを取得する。
例としてコンソールからのデータの呼び出しを行う。

【例】アソシエーションを使用しない

ターミナル

 

$ rails c  
[1] pry(main)> user = User.find(1)
[2] pry(main)> Tweet.where(user_id: user.id)
=> [#<Tweet id: 1, image: "http://photo1.jpg", text: "いい景色だ。", created_at: "2014-12-06 09:00:00", updated_at: "2014-12-06 09:00:00", user_id: 1>,
#<Tweet id: 1, image: "http://photo2.jpg", text: "楽しい思い出は消えない。", created_at: "2014-12-06 10:00:00", updated_at: "2014-12-06 10:00:00", user_id: 1>]

tweetsテーブルに対して、user_idがuserのidと等しいレコードを取得している。
対して、これと同じことをアソシエーションを利用すると以下のように記述できる。

【例】アソシエーションを使用する

 

$ rails c
[1] pry(main)> user = User.find(1)
[2] pry(main)> user.tweets
=> [#<Tweet id: 1, image: "http://photo1.jpg", text: "いい景色だ。", created_at: "2014-12-06 09:00:00", updated_at: "2014-12-06 09:00:00", user_id: 1>,
#<Tweet id: 1, image: "http://photo2.jpg", text: "楽しい思い出は消えない。", created_at: "2014-12-06 10:00:00", updated_at: "2014-12-06 10:00:00", user_id: 1>]

Userモデルに「User has many Tweets」の状態のアソシエーションを定義したため、
Userモデルのインスタンス.tweetsと記述するだけでそのインスタンスが所持している
ツイートを取得することができる。

早速、users_controllerのshowアクション内を編集してアソシエーションを利用してみる。

 問題1:アソシエーションを利用して@tweetsを定義しましょう

作業ファイル:app/controllers/users_controller
ヒント:現在ログイン中のユーザーがつぶやいたツイート達を取得するよう書きます
users_controller.rb
1
2
3
4
5
6
class UsersController < ApplicationController
  def show
    @nickname = current_user.nickname
    @tweets = アソシエーションを使用して記述
   end
end

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

 

 

要点チェック