Railsチュートリアル 第2章 - Toyアプリケーション - アプリケーションの起動まで

# アプリケーション自体を作成するための下準備

スタート地点は、Railsチュートリアルのために構築したDockerコンテナ内からです。まずはRailsアプリケーションを生成するところから始まります。

```:bash
# pwd
/var/www

# rails _5.1.6_ new toy_app
      create  
      create  README.md
...略
Fetching gem metadata from https://rubygems.org/............
Fetching gem metadata from https://rubygems.org/.
Resolving dependencies.....
Fetching rake 12.3.3
Installing rake 12.3.3
Using concurrent-ruby 1.1.5
...略
Bundle complete! 16 Gemfile dependencies, 69 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.
         run  bundle exec spring binstub --all
* bin/rake: Spring inserted
* bin/rails: Spring inserted
```

生成された全部のファイルをGit管理下に置いた上で、一度コミットします。今度はコンテナ側ではなくホスト側に対する操作です。

```:zsh
>>> pwd
~/docker/rails_tutorial_test/toy_app

>>> git add -A
>>> git commit -a -m "new repository"
[master (root-commit) ad2b5bc] new repository
 76 files changed, 1195 insertions(+)
...略

>>> git status
On branch master
nothing to commit, working tree clean
```

リスト2.1の内容どおりに`Gemfile`の内容を変更します。以下のdiffは、`rails new`コマンドにより生成された`Gemfile`との差分です。

```diff:Gemfile
 source 'https://rubygems.org'
 
-git_source(:github) do |repo_name|
-  repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/")
-  "https://github.com/#{repo_name}.git"
-end
-
-
-# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
-gem 'rails', '~> 5.1.6'
-# Use sqlite3 as the database for Active Record
-gem 'sqlite3'
-# Use Puma as the app server
-gem 'puma', '~> 3.7'
-# Use SCSS for stylesheets
-gem 'sass-rails', '~> 5.0'
-# Use Uglifier as compressor for JavaScript assets
-gem 'uglifier', '>= 1.3.0'
-# See https://github.com/rails/execjs#readme for more supported runtimes
-# gem 'therubyracer', platforms: :ruby
-
-# Use CoffeeScript for .coffee assets and views
-gem 'coffee-rails', '~> 4.2'
-# Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks
-gem 'turbolinks', '~> 5'
-# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
-gem 'jbuilder', '~> 2.5'
-# Use Redis adapter to run Action Cable in production
-# gem 'redis', '~> 4.0'
-# Use ActiveModel has_secure_password
-# gem 'bcrypt', '~> 3.1.7'
-
-# Use Capistrano for deployment
-# gem 'capistrano-rails', group: :development
+gem 'rails',        '5.1.6'
+gem 'puma',         '3.9.1'
+gem 'sass-rails',   '5.0.6'
+gem 'uglifier',     '3.2.0'
+gem 'coffee-rails', '4.2.2'
+gem 'jquery-rails', '4.3.1'
+gem 'turbolinks',   '5.0.1'
+gem 'jbuilder',     '2.7.0'
 
 group :development, :test do
-  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
-  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
-  # Adds support for Capybara system testing and selenium driver
-  gem 'capybara', '~> 2.13'
-  gem 'selenium-webdriver'
+  gem 'sqlite3', '1.3.13'
+  gem 'byebug',  '9.0.6', platform: :mri
 end
 
 group :development do
-  # Access an IRB console on exception pages or by using <%= console %> anywhere in the code.
-  gem 'web-console', '>= 3.3.0'
-  gem 'listen', '>= 3.0.5', '< 3.2'
-  # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
-  gem 'spring'
-  gem 'spring-watcher-listen', '~> 2.0.0'
+  gem 'web-console',           '3.5.1'
+  gem 'listen',                '3.1.5'
+  gem 'spring',                '2.0.2'
+  gem 'spring-watcher-listen', '2.0.1'
+end
+
+group :production do
+  gem 'pg', '0.20.0'
 end
 
-# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
-gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
+# Windows環境ではtzinfo-dataというgemを含める必要があります
+gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
```

再びDockerコンテナに対して操作を行います。`bundle install`によるgemのインストール操作です。

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

# bundle install --without production
...略
You have requested:
  spring = 2.0.2

The bundle currently has spring locked at 2.1.0.
Try running `bundle update spring`

If you are updating multiple gems in your Gemfile at once,
try passing them all to `bundle update`
```

`bundle install`が正常に終了しません。そういえば、先に`bundle update`が必要でしたね。

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

# bundle update
...略
Bundle updated!
Gems in the group production were not installed.

# bundle install --without production
...略
Bundle complete! 16 Gemfile dependencies, 64 gems now installed.
Gems in the group production were not installed.
Bundled gems are installed into `/usr/local/bundle`
```

今度こそ`bundle install`まで終了しました。`Gemfile.lock`の中身が変わっているはずなので、ホスト側で一度Gitのローカルリポジトリをコミットしましょう。

```:zsh
>>> pwd
~/rails_tutorial_test/toy_app

>>> git commit -a -m "bundle install completed"
[master cc4dd0f] bundle install completed
 1 file changed, 65 insertions(+), 75 deletions(-)
```

続いて、Githubで`toy_app`リポジトリを作成します。

Githubで`toy_app`リポジトリをした次は、リモートリポジトリをローカルリポジトリと紐付け、ローカルからリモートにプッシュします。

```:zsh
>>> git remote add origin git@github.com:rapidliner0/toy_app.git
>>> git push -u origin --all
...略
To github.com:rapidliner0/toy_app.git
 * [new branch]      master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'. 
```

```:zsh
>>> heroku create
heroku create
Creating app... done, ⬢ nameless-cove-31280
https://nameless-cove-31280.herokuapp.com/ | https://git.heroku.com/nameless-cove-31280.git

>>> git remote add heroku https://git.heroku.com/nameless-cove-31280.git
fatal: remote heroku already exists.

>>> git remote show heroku
* remote heroku
  Fetch URL: https://git.heroku.com/nameless-cove-31280.git
  Push  URL: https://git.heroku.com/nameless-cove-31280.git
  HEAD branch: (unknown)
```

`hello_app`のデプロイ時に行った`heroku create`のときと異なり、`git remote add heroku`なしでリモートリポジトリ`heroku`の定義がされていました。操作内容の違いに心当たりがあるとすれば、以下の事柄の違いです。

* `hello_app`では、`heroku create`を`git remote add`とは違うプロセスのシェルで行った
* `toy_app`では、`heroku create`を`git remote add`と同じプロセスのシェルで行った

# データモデル

## ユーザーのデータモデル

Railsチュートリアルの[2.1.1 ユーザーのモデル設計](https://railstutorial.jp/chapters/toy_app?version=5.1#sec-modeling_demo_users)の内容をUMLのクラス図にすると、以下のような内容になります。

![SoWkIImgAStDuKhEIImkLYWjJYqgLgZcKW22p1GhXSoyajJqr28mFoynDzLAeRYaA3Cl7IoGcfkOcGCNgULoICrB0He50000.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323778/5bf756ae-3e0c-6e9d-64c4-2dababc0f33d.png)

上記クラス図の画像は、以下のPlantUMLソースから生成したものです。

```
@startuml
class users {
    id: integer
    name: string
    email: string
}
@enduml
```

## マイクロポストのデータモデル

Railsチュートリアルの[2.1.2 マイクロポストのモデル設計](https://railstutorial.jp/chapters/toy_app?version=5.1#sec-modeling_demo_microposts)の内容をUMLのクラス図にすると、以下のような内容になります。

![FSmn2i0W38NXtLFa74xUf8W62MWiUN4glNl5eM_xl-4bU3PVeuVICq13Yirxma5Fe3sfaKIT6zlfCdUeHuARQ3ksm7P9_UqDYRNkqmy0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323778/63c425c9-7c6f-aff1-42ef-de5b14764db1.png)

上記クラス図の画像は、以下のPlantUMLソースから生成したものです。

```
@startuml
class microposts {
    id: integer
    content: string
    user_id: string
}
@enduml
```

# `scaffold`を用いた、ユーザーのデータモデルの手軽な実装

今度はDockerコンテナ内での作業となります。

```:bash
# rails generate scaffold User name:string email:string
Could not find pg-0.20.0 in any of the sources
Run `bundle install` to install missing gems.
```

…おや。先に進まないですね。`pg`は本番環境でしか使わないもののはずなのですが…

* [DockerでRailsチュートリアル（Toyアプリ編1） - 桜色HelloWorld](https://rikka-rt.hatenablog.jp/entry/2018/11/17/010809)

どうやら先人も同じところでハマった人がいたようです。先人に心から感謝しつつ、私も先人を参考にさせていただくことにします。

```diff
diff --git a/Gemfile b/Gemfile
index be8fd6c..d585081 100644
--- a/Gemfile
+++ b/Gemfile
@@ -21,9 +21,7 @@ group :development do
   gem 'spring-watcher-listen', '2.0.1'
 end
 
-group :production do
-  gem 'pg', '0.20.0'
-end
+gem 'pg', '0.20.0'
 
 # Windows環境ではtzinfo-dataというgemを含める必要があります
 gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
\ No newline at end of file
```

`bundle install`した上で、改めて`rails generate scaffold`を実行してみます。

```:bash
# bundle install --without production
Fetching gem metadata from https://rubygems.org/............
...略
Bundle complete! 16 Gemfile dependencies, 65 gems now installed.
Gems in the group production were not installed.
Bundled gems are installed into `/usr/local/bundle`

# rails generate scaffold User name:string email:string
Running via Spring preloader in process 671
...略
      invoke  scss
      create    app/assets/stylesheets/scaffolds.scss
```

今度はうまく行ったようです。

# データベースのマイグレート

Dockerコンテナでの作業は続きます。

続いて、`rails db:migrate`コマンドを実行します。データベースを更新し、データモデル（今回は`users`データモデルですね）を作成するためのコマンドです。

```:bash
# rails db:migrate
== 20190730094542 CreateUsers: migrating ======================================
-- create_table(:users)
   -> 0.0106s
== 20190730094542 CreateUsers: migrated (0.0122s) =============================
```

`CreateUsers: migrated`とありますね。正常に完了したようです。

# RailsのローカルサーバーでToyアプリケーションを実行してみる

```:bash
# rails server
=> Booting Puma
=> Rails 5.1.6 application starting in development 
=> Run `rails server -h` for more startup options
Puma starting in single mode...
* Version 3.9.1 (ruby 2.5.1-p57), codename: Private Caller
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://0.0.0.0:3000
Use Ctrl-C to stop
```

ここまでは、第1章`hello_app`と実行結果は変わりません。しかし、その後に何やら見慣れないメッセージが表示されています。

```
   (1.3ms)  SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC
```

どうやら、データベース関係のメッセージのようです。

# `/`を開く

ブラウザでルートURL「/」を開いたときの表示内容も、`hello_app`と変わりません。

<img width="866" alt="スクリーンショット 2019-07-31 5.56.34.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323778/c7f40b82-9b20-b627-0123-3523077dc9a4.png">

`hello_app`と`toy_app`の相違点はこの先にあるのですが、内容が大きく変化する地点になるのでここまでで一投稿とします。