【Rails】[モデル名].rbについて

# 記事概要
Ruby on Railsのモデルについて、まとめる

# 前提
- Ruby on Railsでアプリケーションを作成している

# 基本情報
## ファイルパス
app/models/[モデル名].rb

## 記載方法

## ActiveRecordメソッド
モデルがテーブル操作に関して使用できるメソッドの総称

## アソシエーション
モデルを利用したテーブル同士の関連付けのこと
アソシエーションをモデルに定義すると、そのモデルに紐づく別モデルの情報へアクセスできるようになる

[![Image from Gyazo](https://i.gyazo.com/8647f1bd4dba84152f1bd4011cd76c66.png)](https://gyazo.com/8647f1bd4dba84152f1bd4011cd76c66)

## N+1問題
アソシエーションを利用した場合に限り、データベースへのアクセス回数が多くなってしまう問題であり、アプリケーションのパフォーマンス低下につながる

`includes`メソッドを使用することで、解消される

# まとめ(データ取得)
## whereメソッド
詳細は、[こちら](https://qiita.com/likapantrip/items/655e2c8fc2d4c02eb12e#whereメソッド)を参照

```ruby
def self.search(search)
  if search != ""
    Tweet.where('text LIKE(?)', "%#{search}%")
  else
    Tweet.all
  end
end

# コントローラーで呼び出す
#=> @tweets = Tweet.search(params[:keyword])
```

`if search != ""`は、検索フォームに何か値が入力されていた場合に`true`となる

### 条件に一致したレコード以外を取得
```ruby
モデル名.where.not("条件")

User.where.not(id: current_user.id)
=> カレントユーザー以外を取得する
```

# まとめ(入力制約)
## validatesメソッド
バリデーションを設定する時に使用するメソッド

```ruby
validates :カラム名, バリデーションの種類
```

### presenceオプション
空欄の場合、エラー発生

```ruby
# カラムが「空ではないか」というバリデーションを設定
# 空欄で登録しようとすると、エラー発生
validates :カラム名, presence: true
```

### lengthオプション
文字数制限をチェック

```ruby
# 数字の文字数を超えると、エラー発生
validates :カラム名, length: { maximum: 数字 }
```

### unlessオプション
「メソッドの返り値が`false`ならばバリデーションによる検証を行う」という条件を追加

```ruby
# was_attached?メソッドの返り値が'false'の場合、バリデーションの検証を行う
validates :content, presence: true, unless: :was_attached?

# メソッドの検証を行う(画像がない場合、false)
def was_attached?
  self.image.attached?
end
```

### messageオプション
バリデーションエラー発生時に表示するエラーメッセージを、指定できる

### numericalityオプション
数値かどうかを検証する
数値であればDBに保存を許可し、それ以外では保存が許可されないようにする

```ruby
# 数値の場合、DBにデータが保存される
validates :genre_id, numericality: true
```

### other_thanオプション
指定した値を、DB保存対象外とする

```ruby
# 1以外の数値の場合、DBにデータが保存される
validates :genre_id, numericality: { other_than: 1 }
```

# まとめ(アソシエーション)
## has_manyメソッド
「1対多」のつながりがあることを示すメソッド

```ruby
has_many :モデル名の複数形
```

```ruby
class User < ApplicationRecord
  # 省略
  has_many :tweets
end
```

[![Image from Gyazo](https://i.gyazo.com/f669c1677d4ee964e0d95fe660e6aa3e.png)](https://gyazo.com/f669c1677d4ee964e0d95fe660e6aa3e)

### throughオプション
多対多の関連を定義するときに利用し、中間テーブルを指定する
「〜を経由する」という意味

```tweet.rb
class Tweet < ApplicationRecord
  has_many :tweet_tags
  has_many :tags, through: :tweet_tags
end
```

```tag.rb
class Tag < ApplicationRecord
  has_many :tweet_tags
  has_many :tweets, through: :tweet_tags
end
```

```tweet_tag.rb
class TweetTag < ApplicationRecord
  belongs_to :tweet
  belongs_to :tag
end
```

[![Image from Gyazo](https://i.gyazo.com/c8d25f805196b92a924f2a0c01ccf2b6.png)](https://gyazo.com/c8d25f805196b92a924f2a0c01ccf2b6)

### dependentオプション
親モデルを削除した時に、親モデルと関連している子モデルに対する挙動を指定するオプション

#### :destroy
親モデルが削除されたとき、それに紐付ている子モデルも一緒に削除される

```user.rb
class User < ApplicationRecord
  # 省略

  # usersテーブル(親)のレコードが削除された場合、それに紐づくtweetsテーブル(子)のレコードも同時に削除される
  has_many :tweets, dependent: :destroy
end
```

## belongs_toメソッド
「1対1」のつながりがあることを示すメソッド

`belongs_to`メソッドで紐付けた他モデルのカラムが存在する場合、他モデルのデータをテーブルに保存できる

```ruby
belongs_to :モデル名
```

```ruby
class Tweet < ApplicationRecord
  # 省略
  belongs_to :user
end
```

[![Image from Gyazo](https://i.gyazo.com/71c6a30f4d01bd28d47058fa042a25b1.png)](https://gyazo.com/71c6a30f4d01bd28d47058fa042a25b1)


### 存在チェック
アソシエーションで`belongs_to`を指定した場合、相手モデルのidが「空ではないか」というバリデーションはデフォルトで設定される
そのため、`presence: true`のバリデーションは不要

```ruby
class Tweet < ApplicationRecord
  belongs_to :user
  # presence: trueのバリデーションは不要
  # validates :user_id presence: true
end
```

## has_one_attachedメソッド
各レコードとファイルを1対1の関係で紐づけるメソッド
`has_one_attached`メソッドを記述したモデルの各レコードは、それぞれ1つのファイルを添付できる

※画像を格納するためのカラムは、テーブルに追加不要

```ruby
class モデル < ApplicationRecord
  # ファイル名には、添付するファイルがわかる名前をつける　※ファイル名が、パラメーターのキーになる
  has_one_attached :ファイル名
end

# 添付されたファイルにアクセスする
#=> モデル.ファイル名
```


# Ruby on Railsまとめ
https://qiita.com/likapantrip/items/46b43c9d1309b6633f0a

# モデル
https://qiita.com/likapantrip/items/8cd3ac1a970b1764b7ee