コーディング未経験のPO/PdMのためのRails on Dockerハンズオン vol.3 - Scaffold, RESTful, MVC -

# はじめに
第三回目の今回は、Railsの便利機能を使って簡単なWebアプリケーションを作ってみようと思います。
また、Railsアプリでとても大切な『RESTful』や『MVC』について紹介していきます。

# 前回のソースコード
前回のソースコードはこちらに格納してます。今回のだけやりたい場合はこちらからダウンロードしてください。

- [at946/rails_on_docker_handson at vol.02](https://github.com/at946/rails_on_docker_handson/tree/vol.02)

# ScaffoldでRailsアプリを作ってみる
ScaffoldはRailsの強力な機能の一つで、数コマンドでRails appを作成することができます。
一方で、数コマンドであまりにも多くのことがなされてしまうので勉強する上では頭が混乱してしまうかもしれません。
ただ、Railsアプリの基本がつまったものですので、一度触ってみましょう！

## User管理アプリを作る
Scaffoldを使って、Userを管理するアプリを作ってみます。
まず、webコンテナを立ち上げて、コンテナ内に入って操作していきましょう。

```
$ docker-compose up -d
$ docker-compose exec web ash
```
`docker-compose exec <service> <command>`は`<service>`で`<command>`を実行するコマンドです。`ash`はalpine linuxのシェルです。シェルというと`bash`や`zsh`などが思い浮かぶと思いますが、alpine linuxでは`ash`です。

これでコンテナの中に入れたかと思います。今までローカルでコマンドを実行するときは`$`を頭につけていましたが、コンテナ内でコマンドを実行するときは`#`をつけるようにします。`#`がついている場合は、上のコマンドを実行してコンテナ内に入っていると思ってください。

何も言わずに以下のコマンドを実行してみましょう。

```
# rails generate scaffold user name:string email:string
# rails db:migrate
```
これだけですでに以下のようなアプリができています。 http://localhost:3000/users にアクセスしてみて確かめてみてください。↓のようなアプリが出来上がっているはずです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254216/dfef900c-29cf-66aa-4a48-4cf5a4e83be8.png)
色々と触ってみてください。たった２コマンドでこのアプリができちゃうの強すぎませんか？笑

ではまずコマンドの説明をしておきます。

### rails generate scaffold model_name [field:type...field:type]
`rails generate scaffold`はScaffoldでRailsアプリを作成するコマンドです。`generate`は`g`と省略できます。ちなみにScaffoldは『足場』と和訳されます。

Scaffoldは、1つのModelに対してRESTful（後述）なWebアプリケーションを作成します。`model_name`にはそのModelの名前を入力します。慣習的にModelの名前は単数形を用います。
さらに`field`（属性）と`type`（型）を定義します。この組み合わせは複数定義できます。

このコマンドを叩くだけで、そのModelの生成だけでなくRESTfulなアプリケーションに必要な全てのファイルが生成されるわけです。
具体的にはこの後で説明していきます。

### rails db:migrate
`rails generate scaffold`だけで必要なファイルは生成されているのですが、Databaseへの反映（Tableの作成）がまだできていません。
`rails db:migrate`はマイグレーションファイルと呼ばれるファイルの内容に沿ってDatabaseを操作するためのコマンドです。

先ほどの`rails generate scaffold`で作成されたファイルの中にマイグレーションファイルも含まれています。マイグレーションファイルは`rails generate scaffold`で定義した`field:type`に合わせて生成されています。（マイグレーションファイルは次回のハンズオンで触れます）

さて、Scaffoldで作成したRailsアプリを色々と触っていただいたかと思いますが、Railsアプリには重要な考え方やアーキテクチャとして『RESTful』と『MVC』があります。これらについて紹介しますね。

# RESTful
RESTという言葉をご存知でしょうか？よくREST APIとか言われますよね。
RESTは『REpresentational State Transfer』の略で、『[Fielding Dissertation: CHAPTER 5: Representational State Transfer (REST)](https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm)』で言及されています。Wikipediaによると以下の設計原則を持っています。

> - ステートレスなクライアント/サーバプロトコル
- すべての情報（リソース）に適用できる「よく定義された操作」のセット
- リソースを一意に識別する「汎用的な構文」
- アプリケーションの情報と状態遷移の両方を扱うことができる「ハイパーメディアの使用」

少し表現が難しいっすね。これはあくまでAPIで用いられる設計原則なのですが、RailsはこのRESTの原則にそってシステムを作れるということで`RESTful`と表現されますね。

## 1. ステートレスなクライアント/サーバプロトコル
基本的にステートレスです。サーバー側でクライアントとのステート（状態）を管理せず、同じリクエストであれば同じ結果がいつでも返ってくるように設計することでステート管理の煩わしさをなくしています。

## 2. すべての情報（リソース）に適用できる「よく定義された操作」のセット
リソースに操作が定義されている...
RESTでは`ROA`（Resource Oriented Architecture）を原則としています。リソースを中心に考えるとそれに対する操作とはいわゆる`CRUD`（`Create/Read/Update/Delete`）であるといえます。REST APIではHTTPメソッドの`POST/GET/PATCH(PUT)/DELETE`をそれに対応させて定義しています。
RailsでもROAを原則としてアプリを設計していくことが理想です。

## 3. リソースを一意に識別する「汎用的な構文」
汎用的な構文...なんだこれもうわかりにくくないだろうか。
これは、例えばユーザーモデルであれば`/users`のパスで操作ができる、商品モデルなら`/purchases`のパスで操作できる、って感じです。

## 4. アプリケーションの情報と状態遷移の両方を扱うことができる「ハイパーメディアの使用」
もうなんともですね。笑
これは`HTTP`とか使いましょう。って話です。

まとめると以下のような図になると思ってます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254216/f338afc8-9971-5e4d-ad45-1a31d5a1ee3a.png)
このように、「URL」で「リソース」を指定し「HTTPメソッド」で「操作（CRUD）」を指定するイメージですね。
大切な考え方として「リソース」が主軸にあるということを抑えましょう。

先ほどScaffoldで生成したアプリケーションをみてみても`User`モデルを作成して、参照して、更新して、削除する、アプリケーションでした。アプリケーションを考える上でも、この<b>RESTfulを念頭におきながらアーキテクトする</b>とRailsで超絶作りやすくなりますね。

# MVC
`MVC`は`Model`、`View`、`Controller`の頭文字をとったもので、Webアプリケーションアーキテクチャの１つです。

- `Model`: リソース、ロジック
- `View`: 画面表示、表現
- `Controller`: 入力の受け取りに合わせて`Model`と`View`を使う司令塔

Railsは以下のアーキテクチャになっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254216/5905e0ad-e86f-8616-1e94-7dba87334eac.png)
`Controller`の前に`Router`がいますが、`MVC`の形をとっていることがわかると思います。処理を順を追って紹介していきますね。

## Routing
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254216/a9c3031f-a8ed-a453-ed6f-d256566400d4.png)
ユーザーからリクエストを受け取ると、RailsアプリケーションのRouterはそのHTTPメソッドとパスから定義に合わせてController（のAction）に処理を渡してくれます。

## リソースを処理
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254216/394ad909-da29-4266-4d46-b6c27e48b1ce.png)
リクエストを受け取ったControllerはデータの操作が必要な場合はModelに指示を出します。例えば、『ID=1のユーザーのモデルオブジェクトをくれ！』みたいなやつです。ModelはそれにしたがってDBを更新したりオブジェクトを検索してControllerに返してあげます。

## 画面をお返し
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254216/142d4bdf-c8e1-bfd8-17aa-8b040e2f93dc.png)
Controllerはその後、Viewに画面をレンダリングするように指示を出します。この時、先ほどゲットしたModelの情報などもViewに渡し、Viewはその情報も元にして画面を整形してControllerに返却します。
ControllerはユーザーにViewを渡してあげて、ユーザーのブラウザがそれを表示してくれます。

これらがMVCの、そしてRailsの一連の処理の流れになります。こうやってみるととてもシンプルですよね。MVCがそれぞれ独立したことにより、コードの管理も簡単だし、どこに何をやらせればいいのかもシンプルに考えられるようになると思います。

# RailsのMVCをScaffoldで確認する
RailsのScaffoldはRailsを体現したようなやつなんですよ。なんで当然MVCなわけですね。
てことでScaffoldのソースコードを少し覗きながらMVCを感じてみましょう！

## Router
`Router`の設定は`config/routes.rb`に書きます。覗いてみましょー！

```rb:config/routes.rb
Rails.application.routes.draw do
  resources :users
end
```
え、超シンプルやん。はい、`resouces [controller_name]`でそのControllerに対してRailsアプリケーションで標準的に必要とされるルーティングを全て生成してくれちゃう便利なメソッドです。実際に以下のルーティングを生成してくれちゃいます。

HTTP method|Path|Routing|Route name
-----|----------|-----|-----
GET|/users|users#index|users
POST|/users|users#create|users
GET|/users/new|users#new|new_user
GET|/users/:id/edit|users#edit|edit_user
GET|/users/:id|users#show|user
PATCH|/users/:id|users#update|user
PUT|/users/:id|users#update|user
DELETE|/users/:id|users#destroy|user

見方ですが、例えば１行目であれば
『`GET`メソッドで`/users`にアクセスされた場合、`UsersController`の`index action`にルーティングする。Rails内では`users_path`って名前で定義される』
って感じです。「名前で定義される」ってなんぞ？となると思いますが、この後でてきます。例えばリンク（`<a>`）を作る時にRailsでは`link_to`ヘルパーが使えるのですがその遷移先として`user_path`と指定すれば`/users`と解釈してくれるんです。これ結構便利なんですよねー。

RailsのRouting設定はコマンドラインから確認することができるっす。

```
# rails routes
Prefix     Verb    URI Pattern                Controller#Action
users      GET     /users(.:format)           users#index
           POST    /users(.:format)           users#create
new_user   GET     /users/new(.:format)       users#new
edit_user  GET     /users/:id/edit(.:format)  users#edit
user       GET     /users/:id(.:format)       users#show
           PATCH   /users/:id(.:format)       users#update
           PUT     /users/:id(.:format)       users#update
           DELETE  /users/:id(.:format)       users#destroy
...
```
上の表とおんなじ感じになっていることがわかりますね。

## Controller
さて、RouterによってControllerのActionにリクエストがルーティングされましたんで、Controllerの中身を覗いてみましょう！
Controllerのソースコードは`app/controller/`配下にまとまっています。今回は`user`モデルを作ったので`users_controller.rb`ファイルが生成されていますね。Controllerはその中に複数のactionがあることから`users`のように複数形で名前づけされるルールになってますので気をつけてください！

```rb:app/controller/users_controller.rb
class UsersController < ApplicationController
  before_action :set_user, only: [:show, :edit, :update, :destroy]

  def index
    @user = User.all
  end

  def show
  end

  def new
    @user = User.new
  end

  def edit
  end

  def create
    @user = User.new(user_params)
        
    respond_to do |format|
      if @user.save
        format.html { redirect_to @user, notice: 'User was successfully created.' }
        format.json { render :show, status: :created, location: @user }
      else
        format.html { render :new }
        format.json { render json: @user.errors, status: :unprocessable_entity }
      end
    end
  end

  def update
    respond_to do |format|
      if @user.update(user_params)
        format.html { redirect_to @user, notice: 'User was successfully updated.' }
        format.json { render :show, status: :ok, location: @user }
      else
        format.html { render :edit }
        format.json { render json: @user.errors, status: unprocessable_entity }
      end
    end
  end

  def destroy
    @user.destroy
    respond_to do |format|
      format.html { redirect_to users_url, notice: 'User was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private
    def set_user
      @user = User.find(params[:id])
    end

    def user_params
      params.require(:user).permit(:name, :email)
    end
end
```
ながいっすね。重要なところだけかいつまんで説明します。
まず、`def xxx ... end`となってるブロックがいっぱいありますね。`def`はRubyにおける関数定義です。で、`private`より上にある一つ一つがActionと呼ばれているやつらです。ちょうど先ほどRouterで定義されていたアクションが全てあるのがわかりますね。

その中で１つ、index actionをみてみましょうか。

```rb:app/controllers/users_controller.rb
...
def index
  @user = User.all
end
...
```
中身一行だけですね。
これは`@user`に`User.all`の結果を代入してますね。`User.all`はまた今度詳しく説明予定ですが、Userモデルのデータを全てリスト形式で取得するメソッドです。なのでUserモデルを全件検索したものを`@user`に代入しているんですね。
ここで気になる人がいると思うのですが、`@`ってなんやねんと。これは、<b>インスタンス変数</b>と呼ばれるものになります。対して`@`がつかない変数は<b>ローカル変数</b>と呼びます。
違いは変数の適用範囲です。簡単にいうと<b>ローカル変数はViewに引き渡すことができないのです</b>。対して<b>インスタンス変数はViewに引き渡すことができる</b>のです。MVCの考え方からControllerはViewにModelの情報を引き渡してユーザーに描写する画面を作るので、インスタンス変数を使う必要があるのです。

さて、ControllerがModelからデータを受領しているのはここまででなんとかわかると思いますが、Viewの呼び出しはどうやっているのか...
RailsではViewを呼び出すメソッドとして`render`があります。`users_controller.rb`の中にも`render`と書かれているところがありますがないところもあります。これはどういうことか。
実はRailsでは各Actionの最後に暗にActionと同じ名前のViewに`render`をしています。例えば`index`アクションの場合は、処理の最後に`render :index`というようなことがなされており、これによって`app/views/users/index.html.erb`が呼び出されるようになっています。

## Model
Modelのソースは`app/models/`に作ります。Scaffoldのおかげで`user.rb`ファイルが生成されていますので中身を覗いてみましょう。

```rb:app/models/user.rb
class User < ApplicationRecord
end
```
ApplicationRecordを継承しているので、特に何も書かなくてもDBにアクセスしてCRUDできるようになっています。
追加でバリデーションやロジック（デフォルト値や値の計算など）を書くことができます。（今後やっていきます！）

実際にDBに反映されているテーブルの情報はSchemaをみることで確認することができます。

```rb:db/schema.rb
ActiveRecord::Schema.define(version: 2020_01_16_115651) do

    enable_extention "plpgsql"

    create_table "users", force: :cascade do |t|
        t.string "name"
        t.string "email"
        t.datetime "created_at", precision: 6, null: false
        t.datetime "updated_at", precision: 6, null: false
    end

end
```
String型の`name`、`email`、Datetime型の`created_at`、`updated_at`が`users`テーブルに作られた感じがわかりますよね。

## View
Viewのソースは`app/views/{controller_name}/`ディレクトリに作成します。

```erb:app/views/users/index.html.erb
<p id="notice"><%= notice %></p>

<h1>Users</h1>

<table>
    <thead>
        <tr>
            <th>Name</th>
            <th>Email</th>
            <th colspan="3"></th>
        </tr>
    </thead>

    <tbody>
        <% @users.each do |user| %>
            <tr>
                <td><%= user.name %></td>
                <td><%= user.email %></td>
                <td><%= link_to 'Show', user %></td>
                <td><%= link_to 'Edit', edit_user_path(user) %></td>
                <td><%= link_to 'Destroy', user, method: :delete, data: { confirm: 'Are you sure?' } %></td>
            </tr>
        <% end %>
    </tbody>
</table>

<br>

<%= link_to 'New User', new_user_path %>
```
これは`index`アクションが処理をさせるViewです。ほぼHTMLですね。
ファイルは`.html.erb`拡張子です。`.erb`はembedded Rubyの意で、Rubyのコードを埋め込めるHTMLファイルです。
Rubyコードの埋め込みの仕方には2種類あります。

- <% code %>: このcodeは実行されますが、結果はレンダリングされません。
- <%= code %>: このcodeは実行され、結果はレンダリングされます。

また、ブロック形式で記述することもできます！`index.html.erb`の中でも以下のような表現がありますね。

```erb:app/views/users/index.html.erb
...
<% @users.each do |user| %>
  ...
<% end %>
...
```
この表現は、`@users`（これはControllerで`User.all`が代入されていたやつです。）の配列の中から1つずつ取り出し`user`という変数として、`end`までの処理をまわすという表現です。

はい。ということでScaffoldで作成されたファイルの中身をみながら「へー。RailsはMVCでRESTだなー。」となっていただけましたかね。

と、いうことでせっかく作ったScaffoldですが、便利すぎてお勉強には不向きなところもあるのでリセットして、次回からは１からアプリ開発をしていきたいと思います。

# 後片付け
`rails generate`で作成したファイルや追加されたコードのほとんどは`rails destroy`でもとにもどせます。

```
# rails destroy scaffold user
```
こいつは便利だ。ちなみに`destroy`は`d`と省略することも可能。

しかし、`scaffolds.scss`だけは消えないのでこれは個別に消してあげて！

```
# rm app/assets/stylesheets/scaffolds.scss
```

また、DBにはまだテーブルが存在してる状態です。今回は開発環境ですし、データが消えても問題ないのでDBを再作成してclean upしましょう。

```
# exit
```

```
$ docker-compose down
$ docker-compose run --rm web rails db:migrate:reset
```
`rails db:migrate:reset`はDBを削除（`db:drop`）してまた作り（`db:create`）、マイグレーションを適用する（`db:migrate`）を一度に実行してくれるコマンドです。最初にDBを削除してしまうので本番環境やテストデータを残しておきたい時は<b>絶対に</b>使ってはいけませんよ。

最後にもう一度立ち上がったdbコンテナを落として今日のハンズオンは終了です。

```
$ docker-compose down
```

# まとめ
今回はScaffoldというRailsのアーキテクチャが詰まったアプリを作る機能を紹介しました。
その中でMVCやRESTといったRailsの開発思想が学べましたね。この辺りはアプリのシンプルさを保つためにもぜひものにしておきましょう。

次回からは、何回かに分けてTwitterのようなアプリを１からつくってこうと思います。最初は静的なトップページ。
Bootstrap（CSSフレームワーク）を使っていい感じにデザインしてきますよ！

では、次回も乞うご期待！ここまでお読みいただきありがとうございました！

Next: [コーディング未経験のPO/PdMのためのRails on Dockerハンズオン vol.4 - Static pages - - Qiita](https://qiita.com/at-946/items/22b89cad2750025b65a1)

# 本日のソースコード

- [at946/rails_on_docker_handson at vol.03](https://github.com/at946/rails_on_docker_handson/tree/vol.03)

# Reference
- [Ruby on Rails チュートリアル：実例を使って Rails を学ぼう](https://railstutorial.jp/)
- [Fielding Dissertation: CHAPTER 5: Representational State Transfer (REST)](https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm)
- [Webサービス開発で知っておきたいRESTfulの意味とは？ - WPJ](https://www.webprofessional.jp/what-does-restful-really-mean/)

# Other Hands-on Links
https://github.com/at946/rails_on_docker_handson/tree/master