Active Recordの基礎

# これは何？
[RailsガイドのActive Recordの基礎](https://railsguides.jp/active_record_basics.html)が理解をする上で非常によかったので、
振り返れるようにまとめます。

# Active Recordって何？
MVCのM、つまりモデルに相当するもので、Active Recordを介してデータベースとやりとりができます。
なお、データベースとやりとりをする時の考え方として、ORM（オブジェクトリレーショナルマッピング）を採用しており、
モデルをインスタンス化したオブジェクトと、MySQLのようなRDBを接続することで様々なことを直接SQL文を書かずに実現しています。

# Active Recordの機能
- モデルおよびモデル内のデータを表現する
- モデル間の関連付け(アソシエーション)を表現する
- 関連するモデルを介した継承階層を表現する
- データがデータベースに永続的に保存される前に検証(validation)を行なう
- オブジェクト指向の表記方法でデータベースを操作する

# 覚えるべきルール
- モデルのクラス名の複数形がDBのテーブル名
    - ![image.png](https://qiita-image-store.s3.amazonaws.com/0/180679/786e32b8-6561-8a3d-c9b5-dad282e46a76.png)
- 外部キーはテーブル名の単数形_idにする
    - users, postsテーブルの外部キーはuser_id, post_id
- 主キーは自動生成される

# モデルクラスってどこまで何やってるの？
例えば、
`bundle exec rails generate model User name:string email:string`
でモデルクラスを作成するとします。
（その後、`bundle exec rails db:migrate`とかはやっておいてください）

```
class User < ApplicationRecord
end
```

上記のようなモデルクラスが作成されますが、これがどこまで何をやってるかというと、

- Userモデルとusersテーブルの関連付け。
- usersテーブルの各カラムをUserモデルのインスタンスの属性に関連付け。

をやっています。

そのため、上記のコードだけでもいきなり、

```
user = User.new(name:"test", email:"test@gmail.com")
user.name = "Jiggaman"
user.save
user1 = User.find_by(name:"Jiggaman")
user1.destroy
```

みたいに直接DBを触って出し入れしたりすることができてしまうのです。

# バリデーション
モデルではDBに保存される前にValidationをかけることができます。
基本的には、インスタンスを生成するコントローラーにて、

- create
- save
- update

がされる前にモデルに定義されているValidationを通り、有効な場合のみにDBに保存されるという流れとなります。

なお、Validationを通らずにスキップしてしまうメソッドもあるため、全てがValidationを通ると思わないように注意してください。

`save`をするタイミングでValidationエラーとなると、
`errors.messages`を返します。

そのため、下記のように設定することが可能となります。

```ruby:models/user.rb
class User < ApplicationRecord
 validates :name, presence: true
end
```

```ruby:controllers/users_controller.rb
def create
 user = User.new
 if user.save
  # DBに保存成功
 else
  # DBに保存失敗
  user.errors.full_messages.each do |error|
   puts error
  end
 end
end
```

今回の場合、`name`カラムが空欄のままDBに保存しようとしているため、`validation`にかかってerrorとなります。

なお、`:message`オプションを使用することで、バリデーション失敗時のエラーメッセージをカスタマイズすることができます。

`validates :name, presence: { message: "must be given" }`

### バリデーションヘルパー
[こちら](https://railsguides.jp/active_record_validations.html#%E3%83%90%E3%83%AA%E3%83%87%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%83%98%E3%83%AB%E3%83%91%E3%83%BC)から下記のヘルパーそれぞれの説明を確認可能です。

- acceptance
- validates_associated
- confirmation
- exclusion
- format
- inclusion
- length
- numericality
- presence
- absence
- uniqueness
- validates_with
- validates_each

# コールバック
`Validates`がDBに保存する直前に動作するものだったのに対し、
コールバックは、オブジェクトの状態が切り替わる「前」or「後」で動作します。

オブジェクトの状態が切り替わるタイミングとは、
オブジェクトが作成/保存/更新/削除/検証/DBからの読み込みなどです。

下記が基礎的なコールバックです。

```ruby:models/user.rb
class User < ApplicationRecord
 # createメソッドのタイミングだけ事前にnormalize_nameメソッドが走ります
 before_validation :normalize_name, on: :create
 # create, update両方のタイミングで事後にset_locationメソッドが走ります
 after_validation :set_location, on: [ :create, :update ]
 # 下記のように事前に呼び出すメソッドの内容をブロックで表現することも可能です
 before_create do
  self.name = login.capitalize if name.blank?
 end

 # コールバックメソッドはprivateで宣言してください
 private
  def normalize_name
   self.name = name.downcase.titleize
  end
  
  def set_location
   self.location = LocationService.query(self)
  end
end
```

もう少し詳細な[利用可能なコールバックと順番はこちら](https://railsguides.jp/active_record_callbacks.html#%E5%88%A9%E7%94%A8%E5%8F%AF%E8%83%BD%E3%81%AA%E3%82%B3%E3%83%BC%E3%83%AB%E3%83%90%E3%83%83%E3%82%AF)を参照してください。

# アソシエーション
モデルとモデルを関連づけることによって、はるかに簡単な操作で実現したいことができるようになりますので是非知っておいてください。

効果を実感できない方は、[こちらの例](https://railsguides.jp/association_basics.html#%E9%96%A2%E9%80%A3%E4%BB%98%E3%81%91%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%99%E3%82%8B%E7%90%86%E7%94%B1)を見ることでそのバグツンの効果を実感できると思います。