Railsチュートリアル 第3章 - rails createの裏側で何が行われているのか

# セットアップ - `rails new`によるRailsプロジェクトの作成からHerokuへのデプロイまで

* `rails new`コマンドにより、Railsプロジェクトを新規作成する
* Gemfileを修正する
* `bundle update`コマンドにより、必要なバージョンのGemを入手する
* `bundle install`コマンドにより、Gemfile.lockを生成する
* Gitリポジトリを初期化する
* README.mdを修正する
* `hello`アクションをApplicationコントローラに追加する
* ルートルーティングを設定する
* GitHubとHerokuをリモートリポジトリに設定する
* リモートリポジトリにプッシュする（含むHerokuへのデプロイ）

このパートの内容については、第1章・第2章でも実行したとおりです。[Railsチュートリアルの当該部分](https://railstutorial.jp/chapters/static_pages?version=5.1#cha-static_pages)に記述された手順通りに進めていけば、特にエラーが発生することもなくHerokuへのデプロイを完了させることができました。

本番環境の動作ログは、`heroku logs`コマンドで取得することができます。

```
2019-08-06T23:18:40.051915+00:00 app[api]: Enable Logplex by user {メールアドレス}
...略
2019-08-06T23:20:05.000000+00:00 app[api]: Build succeeded
2019-08-06T23:20:06.462073+00:00 heroku[web.1]: Starting process with command `bin/rails server -p 35147 -e production`
2019-08-06T23:20:11.535330+00:00 heroku[web.1]: State changed from starting to up
2019-08-06T23:20:31.492107+00:00 heroku[router]: at=info method=GET path="/" host=warm-woodland-62915.herokuapp.com request_id=略 fwd=略 dyno=web.1 connect=1ms service=14ms status=200 bytes=393 protocol=https
2019-08-06T23:20:31.485076+00:00 app[web.1]: => Booting Puma
2019-08-06T23:20:31.485118+00:00 app[web.1]: => Rails 5.1.6 application starting in production
2019-08-06T23:20:31.485120+00:00 app[web.1]: => Run `rails server -h` for more startup options
2019-08-06T23:20:31.485130+00:00 app[web.1]: Puma starting in single mode...
...略
2019-08-06T23:20:31.485146+00:00 app[web.1]: Use Ctrl-C to stop
2019-08-06T23:20:31.485153+00:00 app[web.1]: I, [2019-08-06T23:20:31.484938 #4]  INFO -- : [略] Started GET "/" for 210.161.134.37 at 2019-08-06 23:20:31 +0000
...略
2019-08-06T23:20:31.495712+00:00 app[web.1]: I, [2019-08-06T23:20:31.495652 #4]  INFO -- : [略] Completed 200 OK in 7ms (Views: 0.8ms)
2019-08-06T23:20:31.976312+00:00 heroku[router]: at=info method=GET path="/favicon.ico" host=warm-woodland-62915.herokuapp.com request_id=518139ce-c8fe-4327-9730-b9276fd323b3 fwd="210.161.134.37" dyno=web.1 connect=0ms service=1ms status=200 bytes=143 protocol=https
2019-08-06T23:54:19.147024+00:00 heroku[web.1]: Idling
2019-08-06T23:54:19.182120+00:00 heroku[web.1]: State changed from up to down
2019-08-06T23:54:20.044791+00:00 app[web.1]: - Gracefully stopping, waiting for requests to finish
2019-08-06T23:54:20.044829+00:00 app[web.1]: === puma shutdown: 2019-08-06 23:54:20 +0000 ===
2019-08-06T23:54:20.044835+00:00 app[web.1]: - Goodbye!
2019-08-06T23:54:20.044899+00:00 app[web.1]: Exiting
2019-08-06T23:54:20.033813+00:00 heroku[web.1]: Stopping all processes with SIGTERM
2019-08-06T23:54:20.134013+00:00 heroku[web.1]: Process exited with status 0
```

私が`heroku logs`コマンドを実行したところ、以上のようなログが返ってきました。内部で`rails server`が実行されたと思しきログ内容です。

# 演習 - Railsプロジェクトのセットアップ

## 1. ~~Bitbucket~~GitHubがMarkdown記法のREADMEをHTMLとして正しく描画しているか、確認してみてください。

私はリモートリポジトリとしてGitHubを使っているので、ここはGitHubを確認してみます。下記スクリーンショットは、WebブラウザでGitHub上にあるリポジトリ内の`rails_tutorial_sample_app/README.md`にアクセスしたものです。

<img width="1440" alt="スクリーンショット 2019-08-08 7.45.49.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323778/1333cfc2-0847-8311-cf84-51e97b0e764b.png">

## 2.本番環境 (Heroku) のルートURLにアクセスして、デプロイが成功したかどうか確かめてみてください。

<img width="873" alt="スクリーンショット 2019-08-08 7.52.11.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323778/03db4dc6-d6c5-1648-b3ae-75ca3ef9f90a.png">

「hello, world!」が正常に表示されています。デプロイは成功したようです。

# 静的なページの作成に着手する

## Gitブランチstatic-pagesの作成

Railsチュートリアルでは、まず「Gitにトピックブランチstatic-pagesを作成する」というところから始まっています。トピックブランチの生成はGitのローカルリポジトリに対する作業なので、ソースコードが存在するディレクトリで処理を進めます。

```:zsh
>>> pwd
docker/rails_tutorial_test/sample_app

>>> git checkout -b static-pages
Switched to a new branch 'static-pages'
```

## StaticPagesコントローラの生成

続いて、今度はDockerコンテナ側で`rails generate controller`コマンドを実行し、コントローラを生成します。今回生成するコントローラは、名前を`StaticPages`とし、アクションとして`home`と`help`を定義します。

```:bash
# pwd
/var/www/sample_app

# rails generate controller StaticPages home help
Running via Spring preloader in process 32
      create  app/controllers/static_pages_controller.rb
       route  get 'static_pages/help'
       route  get 'static_pages/home'
      invoke  erb
      create    app/views/static_pages
      create    app/views/static_pages/home.html.erb
      create    app/views/static_pages/help.html.erb
      invoke  test_unit
      create    test/controllers/static_pages_controller_test.rb
      invoke  helper
      create    app/helpers/static_pages_helper.rb
      invoke    test_unit
      invoke  assets
      invoke    coffee
      create      app/assets/javascripts/static_pages.coffee
      invoke    scss
      create      app/assets/stylesheets/static_pages.scss
```

正常にコントローラを生成できたようです。

## 変更内容のGitリポジトリへの反映…ローカルからリモートまで

続いて、`rails generate controller`による変更をGitのローカルリポジトリにコミットし、さらにリモートリポジトリにプッシュする手順を行います。

```:zsh
>>> pwd
docker/rails_tutorial_test/sample_app

>>> git branch
  master
* static-pages

>>> git add -A
>>> git commit -m "Add a Static Pages controller"
>>> git push -u origin static-pages
```

このシェル内容の意味するところは、「static-pagesブランチ上にて、以下箇条書きの操作を順に行っている」ということです。

1. 新規作成・修正・削除された全てのファイルをステージングする
2. 指定のコミットメッセージをつけてコミットする
3. `static-pages`リポジトリの内容を、リモートリポジトリ`origin`にプッシュする

以降のRailsチュートリアルにおいても、必要と考えたときに自己判断で順次Gitへのコミット・プッシュを行っていくことになります。

## StaticPagesコントローラに関係するルーティング

`rails generate controller StaticPages`により、`config/routes.rb`の内容は、以下のように変更されました。

```ruby:config/routes.rb
Rails.application.routes.draw do
  get 'static_pages/home'

  get 'static_pages/help'

  root 'application#hello'
end
```

例えば、`get 'static_pages/home'`というのは、「static_pages/homeというURLに対するGETリクエストを、StaticPagesコントローラの`home`アクションと結びつける」という意味の記述になります。`get 'static_pages/help'`であれば、「static_pages/helpというURLに対するGETリクエストを、StaticPagesコントローラの`help`アクションと結びつける」という意味になりますね。

実際、`rails generate controller`によって`app/controllers/static_pages_controller.rb`というファイルも生成されておりまして、実際の内容は以下のとおりとなっています。

```ruby:app/controllers/static_pages_controller.rb
class StaticPagesController < ApplicationController
  def home
  end

  def help
  end
end
```

`app/views/static_pages/`配下には、当該コントローラに対応するビューである`home.html.erb`や`help.html.erb`といったファイルも生成されています。例えば、`home`に対応するビューである`home.html.erb`の内容は以下のとおりです。

```erb:app/views/static_pages/home.html.erb
<h1>StaticPages#home</h1>
<p>Find me in app/views/static_pages/home.html.erb</p>
```

この時点でRailsのdevelopmentサーバーを起動し、`/static_pages/home`をWebブラウザで表示した結果は以下のとおりです。

<img width="873" alt="スクリーンショット 2019-08-13 16.04.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323778/4c0519b9-b73c-1891-2782-359eb8c42b82.png">

# 演習 - 静的なページの生成

## 1. `Foo`というコントローラを生成し、その中に`bar`と`baz`アクションを追加してみてください。

開発環境内で、`rails generate controller Foo bar baz`というコマンドを実行します。実行結果は以下のようになります。

```:bash
# pwd
/var/www/sample_app

# rails generate controller Foo bar baz
Running via Spring preloader in process 92
      create  app/controllers/foo_controller.rb
       route  get 'foo/baz'
       route  get 'foo/bar'
      invoke  erb
      create    app/views/foo
      create    app/views/foo/bar.html.erb
      create    app/views/foo/baz.html.erb
      invoke  test_unit
      create    test/controllers/foo_controller_test.rb
      invoke  helper
      create    app/helpers/foo_helper.rb
      invoke    test_unit
      invoke  assets
      invoke    coffee
      create      app/assets/javascripts/foo.coffee
      invoke    scss
      create      app/assets/stylesheets/foo.scss
```

`rails generate controller Foo bar baz`実行後、Sampleアプリケーション内の各リソースがどうなったか見てみましょう。まず、`config/routes.rb`です。

```ruby:config/routes.rb
Rails.application.routes.draw do
  get 'foo/bar'

  get 'foo/baz'

  get 'static_pages/home'

  get 'static_pages/help'

  root 'application#hello'
end
```

`get 'foo/bar'`、ならびに、`get 'foo/baz'`というルーティングが追加されています。

続いて、`rails generate controller Foo`によって追加された`app/controllers/foo_controller.rb`です。

```ruby:app/controllers/foo_controller.rb
class FooController < ApplicationController
  def bar
  end

  def baz
  end
end
```

確かに`Foo#bar`と`Foo#baz`というアクションが生成されています。

さらに、`rails generate controller Foo bar baz`により、以下2つのビューが追加されました。

* `foo#bar`アクションに対応する`app/views/foo/bar.html.erb`
* `foo#baz`アクションに対応する`app/views/foo/bar.html.erb`

```erb:app/views/foo/bar.html.erb
<h1>Foo#bar</h1>
<p>Find me in app/views/foo/bar.html.erb</p>
```

```erb:app/views/foo/baz.html.erb
<h1>Foo#baz</h1>
<p>Find me in app/views/foo/baz.html.erb</p>
```

この時点でRailsのdevelopmentサーバーを起動し、`/foo/bar`および`/foo/baz`を、順にWebブラウザで表示した結果は以下のとおりです。

<img width="873" alt="スクリーンショット 2019-08-13 17.30.53.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323778/3fc43417-dff8-b962-2d3d-20dd10fa7c34.png">

<img width="873" alt="スクリーンショット 2019-08-13 17.31.20.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323778/94d61be2-cce3-79b5-4664-3209d6f9a0f8.png">

## 2. コラム 3.1で紹介したテクニックを駆使して、`Foo`コントローラとそれに関連するアクションを削除してみてください。 

開発環境内で、`rails destroy controller Foo bar baz`というコマンドを実行します。実行結果は以下のようになります。

```:bash
# pwd
/var/www/sample_app
# rails destroy controller Foo bar baz
Running via Spring preloader in process 123
      remove  app/controllers/foo_controller.rb
       route  get 'foo/baz'
       route  get 'foo/bar'
      invoke  erb
      remove    app/views/foo
      remove    app/views/foo/bar.html.erb
      remove    app/views/foo/baz.html.erb
      invoke  test_unit
      remove    test/controllers/foo_controller_test.rb
      invoke  helper
      remove    app/helpers/foo_helper.rb
      invoke    test_unit
      invoke  assets
      invoke    coffee
      remove      app/assets/javascripts/foo.coffee
      invoke    scss
      remove      app/assets/stylesheets/foo.scss
```

`rails destroy controller Foo bar baz`の実行が終了した時点における、`config/routes.rb`の内容です。

```ruby:config/routes.rb
Rails.application.routes.draw do
  get 'static_pages/home'

  get 'static_pages/help'

  root 'application#hello'
end
```

`get 'foo/bar'`、ならびに、`get 'foo/baz'`というルーティングが、きれいさっぱりなくなっていますね。

# 静的なページの調整

`app/views/static_pages/home.html.erb`、および、`app/views/static_pages/help.html.erb`を、それぞれ以下のように書き換えてみます。

```erb:app/views/static_pages/home.html.erb
<h1>Sample App</h1>
<p>
  This is the home page for the
  <a href="https://railstutorial.jp/">Ruby on Rails Tutorial</a>
  sample application.
</p>
```

```erb:app/views/static_pages/help.html.erb
<h1>Help</h1>
<p>
  Get help on the Ruby on Rails Tutorial at the
  <a href="https://railstutorial.jp/help">Rails Tutorial help page</a>.
  To get help on this sample app, see the
  <a href="https://railstutorial.jp/#ebook"><em>Ruby on Rails Tutorial</em>
  book</a>.
</p>
```

この時点でRailsのdevelopmentサーバーを起動し、`/static_pages/home`、および、`/static_pages/help`をWebブラウザで表示すると、それぞれ結果は以下のとおりになりました。

<img width="873" alt="スクリーンショット 2019-08-13 18.07.57.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323778/318481d1-dd9b-4990-df0e-e9d856498ad3.png">

<img width="1110" alt="スクリーンショット 2019-08-13 18.08.27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323778/70dc95fb-fb79-8afb-e0c0-9d95d3c4e6a0.png">