Railsを使ったToDoリストの作成(3.Railsの基本概念)

#概要
本記事は、初学者がRailsを使ってToDoリストを作成する過程を記したものです。
私と同じく初学者の方で、Railsのアウトプット段階でつまづいている方に向けて基礎の基礎を押さえた解説をしております。
抜け漏れや説明不足など多々あるとは思いますが、読んでくださった方にとって少しでも役に立つ記事であれば幸いです。

#環境
* `Homebrew: 2.5.10` -> MacOSのパッケージ管理ツール
* `ruby: 2.6.5p114` -> Ruby
* `Rails: 6.0.3.4` -> Rails
* `node: 14.3.0` -> Node.js
* `yarn: 1.22.10` -> JSのパッケージ管理ツール
* `Bundler: 2.1.4` -> gemのバージョン管理ツール

```:iTerm
$ brew -v => Homebrew 2.5.10
$ ruby -v => ruby 2.6.5p114
$ rails -v => Rails 6.0.3.4
$ npm version => node: '14.3.0'
$ yarn -v => 1.22.10
$ Bundler -v => Bundler version 2.1.4
```

#第３章　Railsの基本概念
第３章では、Railsで本格的にアプリ開発をする前にRailsにおいて重要な概念を説明していきます。

##1 Railsを使ってWebサイトを表示する
まずは、RailsがどのようにWebサイトを表示しているのか説明します。
Webサイトは、クライアント（ブラウザ）がリクエストを送り、サーバ（ここではRails）がレスポンス（HTMLやCSSファイルをブラウザに送る）したものを、ブラウザが解釈することで表示されています。

ではRailsでは具体的にどのようなことが行われているか見ていきます。

①まず、ブラウザからGETリクエストが飛んできたら`routes.rb`で処理をします。
`routes.rb`はURLを作る場所です。

```config/routes.rb
Rails.application.routes.draw do
  root to: 'boards#index'
end
```
>🙋‍♂️root(localhost:3000)を表示してくださいというリクエストが飛んできたらBoardsControlerのindexメソッドを実行してください

②次に、コントローラです。
コントローラは`routes.rb`からブラウザからのリクエストを受け取り、モデルやビューなどと連携し結果をブラウザに返す役割を担っています。
`routes.rb`の「BoardsControlerのindexメソッドを実行してください」という情報をもとに、コントローラが処理を行います。


```app/controllers/boards_controller.rb
class BoardsController < ApplicationController
    def index
      render 'boards/index' #この部分は省略可能
    end   
end
```
>🙋‍♂️viewsのboardsのindex.html.hamlを表示してください

ちなみにコントローラには命名規則があります。

| 名前 | 例 |
|:-:|:-:|
| コントローラ名  |  boards |
| コントローラのクラス名  |  BoardsController |
|  コントローラのファイル名 | boards_controller.rb  |

上記のように、コントローラ名を「boards」とした場合、コントローラのクラス名は「BoardsController」のようにコントローラ名の先頭を大文字にしてControllerを付けます。このクラスが記載されているファイル名は「コントローラ名_controller.rb」になります。

③最後に、viewsです、viewsにはブラウザに表示したいことを記述します。

```haml:app/views/boards/index.html.haml
%h1 Webサイトの表示
```
![スクリーンショット 2020-11-17 12.58.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864210/9d7d820b-e3b5-9ac5-55e8-f961f07b33d0.png)

上の画像のように表示されていれば完了です。
以上が、RailsがWebサイトを表示する仕組みです。

##2 MVC
###1 MVCとは
MVCとは、Webフレームワークで一般的に取り入れられているアプリケーションの設定を整理するための概念の一つです。
「Model」「Views」「Controller」の頭文字をとって名付けられています。
それぞれに役割があり、ControllerがModelからデータを取得してViewsに表示するという処理が行われています。

![スクリーンショット 2020-11-17 16.13.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864210/ef35830a-8210-8189-634a-e1e815b24dcb.png)
（画像の引用元：https://snome.jp/framework/mvc-model/）


###2 モデルの作成
実際に、操作の対象となる「モデル」を作成します。
モデルを作成するためにはターミナルにて`$rails g model [モデル名(単数形)]`のコマンドを実行します。

```:iTerm
$ rails g model Board
=>create db/migrate/20201117041911_create_boards.rb
  create app/models/board.rb
```
>🙋‍♂️Boardモデルを作成してください
>💻Boardに対応するデータベースのテーブル(migrationファイル)を作成しました
>💻Boardに対応するRubyのクラスを作成しました

モデルの作成が完了していたら以下のようなファイルが作成されているはずです。
コメントアウトされている部分は現在のデータベースの構造(schema)のメモであり、第１章で'annotate'をインストールしたため表示されている。

```app/models/board.rb
# == Schema Information
#
# Table name: boards
#  id          :bigint           not null, primary key
#  created_at  :datetime         not null
#  updated_at  :datetime         not null
#
class Board < ApplicationRecord
end
```

モデルが作成できたら、migrationファイルにcolumnを追加していきます。migrationファイルはデータベースのテーブルを作成するファイルです。
今回はボード（タスクのまとまり）の名前と説明をデータとして扱いたいので、'name'と'description'という２つのcolumnを追加します。
columnを追加する際は`t.[データ型] :[column名]`と入力します。

```20201115023512_create_boards.rb
class CreateBoards < ActiveRecord::Migration[6.0]
  def change
    create_table :boards do |t|
      t.string :name, null: false
      t.text :description, null: false
      t.timestamps
    end
  end
end
```
※`null: false`オプション→このcolumnには絶対に値が入っていないといけないという指定ができます。今回はタスク名とタスクの説明は必須項目のため指定しています。

マイグレーションをデータベース（PostgreSQL）に適用するには、ターミナルにて`$rails db:migrate`を忘れずに実行しましょう。

###3 ActiveRecord
ActoveRecordとは、Railsで採用されているORマッパーです。
ORマッパーとは、オブジェクトとデータベース間の関係を定義するだけで、データベースへのアクセスが行えるシステムのことです。
つまりRubyを使うことでSQLを書かなくてもデータベースにアクセスすることができるということです。<br>
ActiveRecordはRailsにデフォルトでインストールされており、モデルの中で使うことができます。
では、なぜモデルの中で使うことができるのでしょうか？
以下２つのファイルを見てみましょう。

```app/models/board.rb
class Board < ApplicationRecord
end
```

```app/models/application_record.rb
class ApplicationRecord < ActiveRecord::Base
  self.abstract_class = true
end
```
BoardクラスはApplicationRecordクラスを継承しています。
ApplicationRecordクラスはActiveRecord::Baseクラスを継承しています。
つまりBoardクラスがActiveRecord::Baseクラスを継承しているため、モデルの中でActiveRecordを使うことができます。

ActiveRecord::Baseクラスには様々なメソッドが定義されており、それらのメソッドを実行することにより、データベースにアクセスすることができます。

では具体的にどのようなメソッドが定義されているのか？
代表的なものを見ていきましょう。

◆レコードを取得する

```ruby
Board.find(1)
#テーブルから引数に入っているidのレコードを取得する

Board.find_by({column名: ''})
#テーブルからcolumn名でレコードを取得する
#Board.find_by(column名: '') ->  {}を省略しても良い

Board.first,second,third
#テーブルからidが一番若いレコードを取得する

Board.last
#テーブルからidが一番大きいレコードを取得する

Board.all
#テーブルから全てのレコードをを配列として取得する

Board.all.order(:id)
#レコードををid順に並び替えて取得する
#逆順に並べ替えて取得する時は(id: :desc)

Board.all.limit(3)
#テーブルから引数に入っている数だけidの若い順にレコードを取得する

Board.where('id > ?', 2)
#引数の条件に合ったレコードを全て取得する
#条件は文字列で渡す必要がある

Board.count
#データの件数を数える
```

◆データの作成・削除

```ruby
Board.create({name: '', description: ''})
#引数の値を元にインスタンスを作成し、DBに保存する
#board = Board.new({name: 'new', description: 'new'}) -> 空の箱を作る
#board.save -> レコードをDBに保存する

Board.save
#createとは違って保存機能のみ

Board.update
#取得したレコードを更新し保存する
#Board.last -> 対象となるデータを取ってくる
#Board.last.update({column名: ''}) -> 更新する
  
Board.assign_attributes
#取得したレコードを更新するが保存はしない
#board = Board.last
#board.assign_attributes(title: 'assigned')
#board.save

Board.destroy
#取得したレコードを削除する
#board = Board.last -> 削除する対象のデータを取得する
#board.destroy`
```

では実際に、ターミナルでコンソールを立ち上げてデータを作成してみましょう。
ターミナルでコンソールを立ち上げるためには以下のコマンドを実行します。

```:iTerm
$ rails c
```
コンソールが立ち上がったら、createメソッドを実行しましょう。

```:iTerm
irb(main):001:0> Board.create(name: 'console-name1', description: 'console-description1')

   (0.2ms)  BEGIN
  Board Create (4.4ms)  INSERT INTO "boards" ("name", "description", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id"  [["name", "console-name1"], ["description", "console-description1"], ["created_at", "2020-11-17 05:38:06.272799"], ["updated_at", "2020-11-17 05:38:06.272799"]]
   (1.5ms)  COMMIT
=> #<Board id: 1, name: "console-name1", description: "console-description1", created_at: "2020-11-17 05:38:06", updated_at: "2020-11-17 05:38:06">
```

createメソッドを実行することにより、SQLが実行され、テーブルにデータが保存されます。
では、実際に保存されているのかActiveRecord::Baseクラスのallメソッドを使って確かめてみましょう。

```:iTerm
irb(main):002:0> Board.all
  Board Load (0.9ms)  SELECT "boards".* FROM "boards" LIMIT $1  [["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<Board id: 1, name: "console-name1", description: "console-description1", created_at: "2020-11-17 05:38:06", updated_at: "2020-11-17 05:38:06">]>
```

下記のようにデータが作成されていることがわかると思います。

`Board id: 1,
 name: "console-name1", 
 description: "console-description1", 
 created_at: "2020-11-17 05:38:06", 
 updated_at: "2020-11-17 05:38:06">`

以上でActiveRecordの説明は終わりです。
コンソールを終了したい時は`exit`と入力しましょう。