ActiveRecord　学んだ事まとめ

学んだ事を追記していきます。

【参考】[ActiveRecord入門](https://qiita.com/tfrcm/items/80625a75959591c2b7cd)

#whereメソッド
whereメソッドはActiveRecordメソッドのうちの一つです。モデル.where(条件)のように引数部分に条件を指定することで、テーブル内の条件に一致したレコードのインスタンスを配列型で取得できます。

また、whereメソッドを連続して記述することによって、複数の条件に一致したレコードを取得することもできます。

```terminal
[1] pry(main)> Tweet.where('id < 3')
  => [＃<Tweet id: 1, image: "test1.jpg", text: "いい景色だ。", created_at: "2014-12-06 00:00:00", updated_at: "2014-12-06 00:00:00", user_id: 1>,＃<Tweet id: 2, image: "test2.jpg", text: "Thank you!", created_at: "2014-12-07 00:00:00", updated_at: "2014-12-07 00:00:00", user_id: 2>]
  # idが3未満のtweetsテーブルのインスタンスを配列で取得

  [2] pry(main)> Tweet.where('id < 3').where(user_id: 1)
  => [＃<Tweet id: 1, image: "test1.jpg", text: "いい景色だ。", created_at: "2014-12-06 00:00:00", updated_at: "2014-12-06 00:00:00", user_id: 1>]
  # idが3未満かつuser_idが1のtweetsテーブルのインスタンスを配列で取得
```

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

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

① モデルクラスに**has_many**や**belongs_to**などの定義がされている

② 所属する側のテーブルに**所属するクラス名_id**というカラムがある

例えばツイッターの投稿者とツイートは下記のような関係です。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/256717/3b062f2f-5b02-0834-9fe4-09e914e11dc2.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/256717/d462f962-e12a-2579-62bb-9eeea5889192.png)

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

```User.rb
class User < ActiveRecord::Base
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable
  has_many :tweets
end
```

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

```Tweet.rb
class Tweet < ActiveRecord::Base
  belongs_to :user
end
```

アソシエーションを定義すると、モデルをまたいだデータの呼び出しをより直感的に行うことができます。

例えば、下記のように簡潔に書けます。
**従来の場合**
whereメソッドを使用

```console
$ 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>]
```

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

```terminal
$ 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>]

```

#ポリモーフィック関連
ポリモーフィックは、関連付けのやや高度な応用です。ある1つのモデルが他の複数のモデルに属していることを、1つのアソシエーション定義だけで表現することができます。例えば、画像をアップロードして、ユーザーの画像や企業の画像に設定できるサービスがあるとします。アップロードされた画像は、ユーザーの画像もしくは企業の画像として紐付けられます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/256717/9729f20b-9e15-4ace-585f-36be4fbf93e3.png)

```rb
class Image < ActiveRecord::Base
  belongs_to :imageable, polymorphic: true
end

class Company < ActiveRecord::Base
  has_many :images, as: :imageable
end

class User < ActiveRecord::Base
  has_many :images, as: :imageable
end
```
テーブルのカラムは以下の通り。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/256717/2799e115-b7d0-60e3-8b68-cca8c71dad82.png)

#ActiveRecord コールバック
ActiveRecordコールバックとは、作成/保存/更新/削除/検証/等、特定のイベント発生時に呼び出されるメソッドのことです。


**利用可能なコールバック**


**オブジェクトの作成**
<ul><li>before_validation</li<li>after_validation</li><li>before_save</li><li>around_save</li><li>before_create</li><li>around_create</li><li>after_create</li><li>after_save</li></ul>
**オブジェクトの更新**
<ul><li>before_validation</li><li>after_validation</li><li>before_save</li><li>around_save</li><li>before_update</li><li>around_update</li><li>after_update</li><li>after_save</li></ul>

**オブジェクトのdestroy**
<ul><li>before_destroy</li><li>around_destroy</li><li>after_destroy</li></ul>

#updateメソッド
updateはActiveRecordメソッドのうちの一つです。updateメソッドはモデルのインスタンスに対して使用することで、引数内の情報にレコードを更新することができます。

【例】

```terminal
[1] pry(main)> tweet = Tweet.create(user_id: 1, text: "Hello", image: "test.jpg")
=> ＃<Tweet id: 1, user_id: 1, text: "Hello", image: "test.jpg", created_at: "2014-12-10 00:00:00", updated_at: "2014-12-10 00:00:00">
[2] pry(main)> tweet.update(text: "Thank you!")
=> true
[3] pry(main)> tweet
=> ＃<Tweet id: 1, user_id: 1, text: "Thank you!", image: "test.jpg", created_at: "2014-12-10 00:00:00", updated_at: "2014-12-10 00:01:00">
```

#first_or_initializeメソッド
whereメソッドとともに使うことで、whereで検索した条件のレコードがあればそのレコードのインスタンスを返し、なければ新しくインスタンスを作るメソッドです。

【例】

```terminal
user = User.where(nickname: "Shinbo").first_or_initialize
=> #<User id: 1, nickname: "Shinbo">
```

#orderメソッド
データベースからデータ取得時にデータをどう並び替えるかというのが指定できます。
引数には並び替える基準のカラムと、DESC(降順)かASC(昇順)のどちらかの2つを指定することにより順番を指定して取得することができます。

```rb
モデル名.order('カラム名 順序')
```

#limitメソッド
limitメソッド はデータをいくつ取得するかというのが指定できるメソッドで、引数には取得したい件数を指定します。

```rb
 モデル名.limit(取得件数)
```

#averageメソッド

averageメソッドは、averageメソッドを利用するインスタンス取得先のテーブルのカラムを、シンボル型で引数にとります。その値の平均を、小数点ありの状態で返してくれます。

```rb
students = Student.all
  students.average(:score)
  #=> 小数点まで含んだ平均点
```

###roundメソッド
利用した数字の小数点以下を四捨五入します。


```rb
10.4.round
  #=> 10

  10.5.round
  #=> 11
```

#groupメソッド
テーブルのレコードを指定したカラムでまとめた状態で取得します。

【例】

```terminal
Review.group(:product_id)
  Review Load (10.5ms)  SELECT `reviews`.* FROM `reviews` GROUP BY product_id
=> [#<Review id: 1, nickname: "まいき", rate: 1, review: "おもしろい", product_id: 21, created_at: "2014-11-05 16:03:39", updated_at: "2014-11-05 16:03:39", user_id: 4>,
  #<Review id: 3, nickname: "えいちゃん", rate: 10, review: "感動した！また見たい", product_id: 22, created_at: "2014-11-05 16:03:39", updated_at: "2014-11-05 16:03:39", user_id: 4>,
  #<Review id: 13, nickname: "ごとう", rate: 10, review: "思っていたより良かった", product_id: 23, created_at: "2014-11-05 16:03:39", updated_at: "2014-11-05 16:03:39", user_id: 4>
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/256717/c4f8d6d4-531e-6f95-607a-e6ed583ad7ea.png)


#countメソッド
ountメソッドは配列などの要素数を返すメソッドです。groupメソッドに続けて使うとまとめられたそれぞれのレコードの数が取得できます。実行例は下記の通りです。

```terminal
Review.group(:product_id).count
=> {21=>2, 22=>1, 23=>4}
```

###order('count_カラム名').count(カラム名)
countメソッドの引数にカラム名を指定することができます。するとorderメソッドでcount_カラム名でのソートが可能となります。これはそのカラムを持つレコードの数でソートするという意味です。

#keysメソッド
ハッシュはkeysというメソッドを持っています。これはハッシュのキーだけを取り出して配列として返すメソッドです。

#mapメソッド
mapメソッドは配列クラスに定義されているインスタンスメソッドです。mapメソッドは配列の中身を１つずつ取り出してブロックという構文を繰り返し実行します。そして、ブロックの返り値を集めた新しい配列を作成します

```rb
配列オブジェクト.map {|ele| ブロックの処理}
  # eleには配列の要素が１つずつ代入される
  # ブロックの処理は配列の要素の数だけ繰り返し実行される
```