RailsのModelで使うCRUD用メソッドについて

# CRUDとは

> CRUD（クラッド）とは、ほとんど全てのコンピュータソフトウェアが持つ永続性（データを生成したプログラムが終了してもそのデータが存続する特性）の4つの基本機能のイニシャルを並べた用語。

[Wikipedia / CRUD](https://ja.wikipedia.org/wiki/CRUD)

## データベースアプリケーション

> CRUD はリレーショナルデータベースやRESTfulなWebアプリケーションで実装する必要のある主な機能を列挙したものと見ることができる。各文字は標準のSQL文に次のようにマッピング可能である。

<table class="wikitable">
<tbody><tr>
<th>名前</th>
<th>操作</th>
<th>SQL</th>
</tr>
<tr>
<td>Create</td>
<td>生成</td>
<td>INSERT</td>
</tr>
<tr>
<td>Read</td>
<td>読み取り</td>
<td>SELECT</td>
</tr>
<tr>
<td>Update</td>
<td>更新</td>
<td>UPDATE</td>
</tr>
<tr>
<td>Delete</td>
<td>削除</td>
<td>DELETE</td>
</tr>
</tbody></table>

# 環境

- Ruby 2.4.1
- Rails 5.0.7

# Modelの下準備

リソースの操作対象となる Model から作成していきます。

## Modelの作成

下記コマンドで、`Article`モデルを作成します。`Article` は `content` というメッセージ内容（文字列）を持つようにします。

```bash
$ rails g model Article content:string
```

上記のコマンドによって、下記のファイルを自動生成しました。

- `db/migrate/20180604042236_create_articles.rb`
    - これはマイグレーションファイルで、Railsからデータベースのテーブルを管理するためのファイル
    - ファイルの中身は`articles`テーブル作成のコマンドです（モデルは`Article`）
    - マイグレーションファイルが作成しただけではテーブルを作成できません。作成は↓
    - マイグレーションファイルの実行は`rails db:migrate`
    - 今後もテーブルを作成したり変更したりするときはマイグレーションファイルで管理します
- `app/models/article.rb`
    - このファイル（モデルファイル）を開くと`ApplicationRecord`クラスを継承している
    - `app/models/application_record.rb`をみると`ApplicationRecord`クラスは、`ActiveRecord::Base`を継承している
    - なので、`Article`モデルにはそれらの機能が全て入っていて`Article`クラスにコードがなくてもモデル操作できるようになります
    - `ActiveRecord`を継承することによって、SQLをあまり書かず、Rubyだけでレコードを操作が可能になります


# Modelで使えるCRUD用メソッド一覧

メソッド名        | 用途                       
------------ | -------------------------
all          | 全レコードを取得                 
new          | 新規レコードのモデルインスタンスを作成      
find         | id指定で検索                  
find_by      | id以外でも指定して検索             
where        | 検索条件を文字列、配列、ハッシュのどれかで与えれる
first        | 最初のレコードを1件だけ取得           
save         | レコードの作成                  
update, save | データの更新                   
destroy      | データの削除                   

**モデルのメソッドを使うと、SQLを書くことがほとんど無くなります**

上記のメソッドは、`モデルのインスタンス.メソッド名`で使用します。

# rails consoleでモデルのCRUD操作

```bash
$ rails c
```

## モデルの一覧を確認

`Article.all`はDB上に保存されている`Article`モデルのレコード一覧を確認できます。まだカラ（`#<ActiveRecord::Relation []>`）ですが。

```console
> Article.all
  Article Load (0.3ms)  SELECT `articles`.* FROM `articles`
 => #<ActiveRecord::Relation []> 
```

## モデルのインスタンスを作成

モデルのインスタンスは `new` で作成し、変数に代入します

```console
> article = Article.new(content: 'something')
 => #<Article id: nil, content: "something", created_at: nil, updated_at: nil>
```

変数に代入したので、変数だけでも実行できます。

```console
> article
 => #<Article id: nil, content: "something", created_at: nil, updated_at: nil>
```

変数だけで、インスタンスの内容が確認できました。

## モデルのインスタンスに値を代入

```console
> article.content = 'something_updated'
 => "something_updated" 
```

ですが、まだ`Article.all`しても確認できません。

## モデルのインスタンスをDBに保存

```console
> article
 => #<Article id: nil, content: "something_updated", created_at: nil, updated_at: nil> 
2.4.1 :008 > article.save
   (0.4ms)  BEGIN
  SQL (0.2ms)  INSERT INTO `articles` (`content`, `created_at`, `updated_at`) VALUES ('something_updated', '2018-06-04 06:01:12', '2018-06-04 06:01:12')
   (2.0ms)  COMMIT
 => true 
```

`article.save`を実行すると、自動的にデータベース内の`articles`テーブルに保存されます。これに関してですが、モデル名とテーブル名には命名ルールがあります。`articles`テーブルとモデルを関連付けたい場合には、モデル名は先頭が大文字の単数形`Article`でなければいけません。

モデル        | テーブル                       
------------ | -------------------------
Article（先頭が大文字の単数形）      | articles（複数形）

これで、Railsを経由して、データが`INSERT`されたので、`Article.all`で確認できるかと思います。

```console
> Article.all
  Article Load (0.3ms)  SELECT `articles`.* FROM `articles`
 => #<ActiveRecord::Relation [#<Article id: 1, content: "something_updated", created_at: "2018-06-04 06:01:12", updated_at: "2018-06-04 06:01:12">]> 
```

## モデルのインスタンスを取得

### 何個かレコードを作成

```
article = Article.new(content: 'something2')
article.save
article = Article.new(content: 'something3')
article.save
```

### **all**

レコード全体を取得します。

### **first**

最初のインスタンスを1つだけ取得します。

### **find**

`id`から検索し、レコードを検索して任意のレコードを１つ取得します。

```console
> Article.find(1)
  Article Load (0.4ms)  SELECT  `articles`.* FROM `articles` WHERE `articles`.`id` = 1 LIMIT 1
 => #<Article id: 1, content: "something_updated", created_at: "2018-06-04 06:01:12", updated_at: "2018-06-04 06:01:12"> 
```

### **find_by**

上の`find`と違うポイントは、 `id`以外でも検索・取得できます。

```console
> Article.find_by(content: 'something2')
  Article Load (0.3ms)  SELECT  `articles`.* FROM `articles` WHERE `articles`.`content` = 'something2' LIMIT 1
 => #<Article id: 2, content: "something2", created_at: "2018-06-04 06:20:18", updated_at: "2018-06-04 06:20:18"> 
```

### **where**

```console
> Article.where(content: 'something3')
  Article Load (0.6ms)  SELECT `articles`.* FROM `articles` WHERE `articles`.`content` = 'something3'
 => #<ActiveRecord::Relation [#<Article id: 3, content: "something3", created_at: "2018-06-04 06:20:24", updated_at: "2018-06-04 06:20:24">]>  
```

また、`where`は、`all`と同じく複数取得が可能です。比較演算子を用いることもできます。

```console
> Article.where('id >=2')
  Article Load (0.4ms)  SELECT `articles`.* FROM `articles` WHERE (id >=2)
 => #<ActiveRecord::Relation [#<Article id: 2, content: "something2", created_at: "2018-06-04 06:20:18", updated_at: "2018-06-04 06:20:18">, #<Article id: 3, content: "something3", created_at: "2018-06-04 06:20:24", updated_at: "2018-06-04 06:20:24">]>
```

## レコードの更新（Update）

レコードの更新には `Update` を使用します。

```console
Article.first.update(content: 'なにか')
  Article Load (0.6ms)  SELECT  `articles`.* FROM `articles` ORDER BY `articles`.`id` ASC LIMIT 1
   (0.1ms)  BEGIN
  SQL (0.2ms)  UPDATE `articles` SET `content` = 'なにか', `updated_at` = '2018-06-04 06:37:04' WHERE `articles`.`id` = 1
   (1.8ms)  COMMIT
 => true 
```

## レコードの削除（Delete）

レコードの削除には `destroy` を使用します。`all`メソッドで取得したら消されたことが確認できます。

```console
> Article.first.destroy
  Article Load (0.4ms)  SELECT  `articles`.* FROM `articles` ORDER BY `articles`.`id` ASC LIMIT 1
   (0.1ms)  BEGIN
  SQL (0.1ms)  DELETE FROM `articles` WHERE `articles`.`id` = 1
   (1.6ms)  COMMIT
 => #<Article id: 1, content: "なにか", created_at: "2018-06-04 06:01:12", updated_at: "2018-06-04 06:37:04"> 

> Article.all
  Article Load (0.4ms)  SELECT `articles`.* FROM `articles`
 => #<ActiveRecord::Relation [#<Article id: 2, content: "something2", created_at: "2018-06-04 06:20:18", updated_at: "2018-06-04 06:20:18">, #<Article id: 3, content: "something3", created_at: "2018-06-04 06:20:24", updated_at: "2018-06-04 06:20:24">]> 
```

---

以上です。ありがとうございました。