超最低限のRailsアプリを丁寧に作る（もう一度きちんと復習して初心者を卒業しよう）

# この記事の基本的な方針
0からアプリケーションを立ち上げるとき、どういう手順で行うでしょうか？
考えれば考えるほどやりたいことややらなければならないことが溢れてくると思いますが、
「全てのアプリケーションに共通した超最低限のものをまず組む」、そして「必要に応じてどんどん拡張してゆく」が正しい手順です。
では<b>全てのアプリケーションに共通した超最低限のもの</b>とはなんでしょうか？
それはログイン機能です。
ここでは、「新規登録画面」・「ログイン画面」・「インデックス画面」のたった3画面のアプリを作ります。インデックス画面は、ログイン状態であれば「自身のemailアドレス」と「ログアウトのリンク」が表示され、非ログイン状態であれば「新規登録のリンク」と「ログインのリンク」が表示されます。以下が完成です。


【TOP画面(ログイン前)】             　　　 【TOP画面(ログイン後)】
<img width="230" display="inline" alt="a0.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559746/066baa43-6945-9174-0040-403550137cbe.png">    <img width="230" alt="a9.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559746/23eb0bd8-130a-e4f5-2c6e-2e5071388877.png">
【登録画面】
<img width="230" alt="a1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559746/a0c57e94-7fd4-45ee-34c7-bf08dcb9a4a5.png">
【ログイン画面】
<img width="230" alt="a2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559746/8c1ea7d6-3f1b-5624-71b8-50a5f16770b3.png">
# 想定する読み手
既に一度Railsアプリをチュートリアルやスクール等で作ったことがある方を想定しております。
Mac使用で、パソコンの環境構築は完了していることが前提です。
# 具体的なコーディング手順
[完成品GitHub](https://github.com/annaPanda8170/minimum_rails_application)
## ①アプリを立ち上げる
まずターミナルを開き`cd`コマンドを使い、アプリを立ち上げたい場所に移動します。
今回はデスクトップに作ります。

```bash:Terminal
$ cd    #ルートディレクトリに移動する
$ cd Desktop   #デスクトップに移動する
```

アプリを立ち上げるために`rails new`をするのですが、まずRailsのバージョンと使用するデータベースを決めます。
バージョンについては指定する必要がなければ記載する必要はありません。記載しなければ自身のパソコンに入っているRailsに基づいて一番最新のものになります。
指定する必要があれば、どのバージョンを指定できるかを確認します。以下をターミナルで打ちます。

```bash:Terminal
$ gem list
```

するとパソコンに入っているgemのリスト一覧が出てくるのでRailsを探します。探すのが面倒であれば`gem list -e rails`とすればRailsのみが出てきます。
私のパソコンだと

```bash:Output
rails (5.2.4.1, 5.2.4, 5.2.3, 5.2.1, 5.1.7, 5.0.7.2)
```

と出てくるのですが、これは今この6つのバージョンでRailsアプリを作れますよということなので、今回は5.2.3にすることにし、

```bash:Terminal
$ rails _5.2.3_ new <名前> -d myspl
```

します。
あ、`-d mysql`はMySQLをデータベースとして使用しますよって意味です。なにも書かないと`sqlite3`っていうのになるそうですが、私はMySQLしか使ったことないのでよくわかりません。もし`rails new`する時点でデータベースを指定していなかったとしても`config/database.yml`の中を書き換えてgemをインストールすればMySQLを使えます。

これでアプリが立ち上げられたと思うので、そのアプリのルートディレクトリに移動します。

```bash:Terminal
$ cd <名前>
```

データベースを作ります。

```bash:Terminal
$ rails db:create
```

（中身が空であってもこの時点でデータベースは作っておかないと、ブラウザでアクセスした時に`ActiveRecord::NoDatabaseError`になってしまいます。）



そして

```bash:Terminal
rails  s
```

でサーバーを立ち上げて、ブラウザで`localhost:3000/`にアクセスすると
<img width="400" alt="rails new.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559746/a4a1f857-28b0-e4b4-d20a-2f140f357261.jpeg">
これが表示されます。
（ところでバージョン指定したのに`5.2.4.1`になってしまっているのはなぜかわかりません。もう少し離れたバージョンだとその通りになります。）
（追記：この件についてコメントをいただきましたので、ここで迷っておられる方は下のコメント欄をご覧くださいませ。）


## ②インデックス画面を表示できるようにする
コントローラを作ります。

```bash:Terminal
$ rails g controller <名前>
```

名前は自由ですが一番関連のある（データベースの）テーブル名の複数形にするのが一般的です。
このコマンドでコントローラとビューに関するファイルが作られます。

```bash:Terminal
$ rails g controller <名前> index
```

のように名前の後にアクションを並べれば、そのアクション用のhtml.erbファイルが作られ、ルーティングとコントローラファイルに必要なことが追記されます。アクションはもちろん複数並べてよく、コンマ無しで隙間だけ開けて並べていきます。

ここでエディタを起動します。

まずルーティングを設定をします。上でアクション名を並べていればすでに書かれています。

```ruby:config/routes.rb
get "コントローラ名/index"
```

取り急ぎ、適当にビューを書きます。

```erb:app/views/コントローラ名/index.html.erb
<div>こんにちは</div>
```

ここでブラウザで`localhost:3000/コントローラ名/index`にアクセスすれば、「こんにちは」が見れるはずです。


通常メインのindex画面をルート画面とするので

```ruby:config/routes.rb
root "コントローラ名#index"
```

を追記しておきます。`localhost:3000`でもアクセスできるようになります。

ルーティングの書き方はいくつかあり、`get "名前", to: "コントローラ名#index"`とすれば`localhost:3000/名前`でアクセスできるようになりますし、`resources`を使った方法もあります。
え？エラーになりますか？
` / `と` # `を間違えていませんか？
` , `を忘れていませんか？

## ③ログイン機能を作る
ログイン機能は自作することもできますが、deviseというgemを使うことが極めて一般的であるのでこれを今回は使用します。

deviseをインストールします。

```ruby:Gemfile
gem 'devise'
```

こちらを追記し、ターミナルで

```bash:Terminal
$ bundle install
```

をし、サーバーを`control + c`で停止し`rails s`で再び起動します。
サーバーの再起動忘れが原因のエラーは世界中で大量発生しているので注意しましょう（笑）

そしてdeviseを使い始めるにはターミナルで

```bash:Terminal
rails g devise:install
```

をする必要があります。これでconfigディレクトリにファイルができたので、またサーバの再起動の必要があります。
さらに、

```bash:Terminal
rails g devise <モデル名>
```

をすれば必要ないくつかのファイルが作られます。この時のモデル名はなんでもいいのですが、userとするのが一般的です。deviseに関するあらゆる記事がこの名前をuserにしたことを前提としたものであり、これ以外にすると思わぬエラーが出る可能性があります。例えば名前をxxxとした場合、普通ログイン中かを確認するメソッドが`user_signed_in?`であるところ、`xxx_signed_in?`となったりします。

続いて、上の`rails g devise <モデル名>` でマイグレーションファイルも作られているので、

```bash:Terminal
$ rails db:migrate
```

します。これでデータベースにユーザー情報用のテーブルが作られます。

deviseはデフォルトではEmailとPasswordで登録する仕様になっています。逆に、このままの仕様でよければビューもルーティングの記述もコントローラもすでに`rails g devise <モデル名>` で準備されています。
ビューとコントローラは隠れているので現時点では見れません。EmailやPassword以外を含めて登録する場合やビューやコントローラを編集する場合は別の手続きが必要です。

さてこの時点でURIをブラウザに直接打ち込めば新規登録画面とログイン画面が表示される段階まで来ています。
さてではURIは何と打ち込めばいいのでしょうか？まずはもちろん`config/routes.rb`を見にいきます。上の`rails g devise <名前>`で自動的に`devise_for :users`が書き込まれていますがこれでは何と打ち込めばいいかわかりません。
ので、ターミナルで

```bash:Terminal
$ rails routes
```

をしてみます。

```bash:Output
                   Prefix Verb   URI Pattern                                                                              Controller#Action
         new_user_session GET    /users/sign_in(.:format)                                                                 devise/sessions#new
             user_session POST   /users/sign_in(.:format)                                                                 devise/sessions#create
     destroy_user_session DELETE /users/sign_out(.:format)                                                                devise/sessions#destroy
        new_user_password GET    /users/password/new(.:format)                                                            devise/passwords#new
       edit_user_password GET    /users/password/edit(.:format)                                                           devise/passwords#edit
            user_password PATCH  /users/password(.:format)                                                                devise/passwords#update
                          PUT    /users/password(.:format)                                                                devise/passwords#update
                          POST   /users/password(.:format)                                                                devise/passwords#create
 cancel_user_registration GET    /users/cancel(.:format)                                                                  devise/registrations#cancel
    new_user_registration GET    /users/sign_up(.:format)                                                                 devise/registrations#new
   edit_user_registration GET    /users/edit(.:format)                                                                    devise/registrations#edit
        user_registration PATCH  /users(.:format)                                                                         devise/registrations#update
                          PUT    /users(.:format)                                                                         devise/registrations#update
                          DELETE /users(.:format)                                                                         devise/registrations#destroy
                          POST   /users(.:format)                                                                         devise/registrations#create
              users_index GET    /users/index(.:format)                                                                   users#index
                     root GET    /                                                                                        users#index
       rails_service_blob GET    /rails/active_storage/blobs/:signed_id/*filename(.:format)                               active_storage/blobs#show
rails_blob_representation GET    /rails/active_storage/representations/:signed_blob_id/:variation_key/*filename(.:format) active_storage/representations#show
       rails_disk_service GET    /rails/active_storage/disk/:encoded_key/*filename(.:format)                              active_storage/disk#show
update_rails_disk_service PUT    /rails/active_storage/disk/:encoded_token(.:format)                                      active_storage/disk#update
     rails_direct_uploads POST   /rails/active_storage/direct_uploads(.:format)                                           active_storage/direct_uploads#create
```

これでこのプロジェクトのURIの状況が手に取るようにわかります。
詳しい説明は省きますが、新規登録（サインアップ）へのURIは`GET    /users/sign_up`で、ログイン（サインイン）画面へのURIは`GET    /users/sign_in`です。
`/`以下を`localhost:3000`に続けて`localhost:3000/users/sign_up`とブラウザに打てば、
<img width="300" alt="in.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559746/d507a04f-8a1a-8524-584f-2cbb401ae5d6.png">
このように表示されます。`localhost:3000/users/sign_in`も同様に表示されるはずです。
ここで適当に新規登録をしてみて、成功すると自動的にログイン状態になり、『こんにちは』のTOP画面に遷移します。これもログインしたらルート画面に遷移しますというdeviseのデフォルトの機能です。もし上で`config/routes.rb`に`root "コントローラ名#index"`を設定していなければ、もちろん
<img width="400" alt="rails new.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559746/a4a1f857-28b0-e4b4-d20a-2f140f357261.jpeg">
が表示されることとなります。
これでログイン機能完成です。

ちなみにログイン機能はdeviseを使わなくても、ユーザー情報をformで入力させそれをデータベースに保存できるよにし、さらにログイン時にsession変数にそのユーザーのユニークな情報（普通はユーザーIDかEmail）を代入し、ログアウト時にsession変数を空にする処理をすれば概ね実装できます。ただ、その後にパスワードを暗号化したり色々必要なことが出てくるので、deviseを使ってしまうことをおすすめします。
## ④TOP画面作成
さてあとは今『こんにちは』になっている、TOP画面を作れば完成です。
TOP画面は、
ログイン状態であれば、そのユーザーのEmailアドレスとログアウトへのリンク、
非ログイン状態であれば、新規登録へのリンクとログインへのリンクが表示されるようにします。
全体を一度に載せてみます。

```app/views/コントローラ名/index.html.erb
<% if user_signed_in? %>
  <%= current_user.email %>
  <%= link_to 'ログアウト', destroy_user_session_path, method: :delete %>
<% else %>
  <%= link_to '新規登録', new_user_registration_path %>
  <%= link_to 'ログイン', new_user_session_path %>
<% end %>
```

まず、このファイルのように拡張子を`.html.erb`とすれば、HTMLファイルにRubyのコードを埋め込めるようになります。裏を返せば普通のHTMLファイルでは条件分岐なんて出来ません。
Rubyのコードを埋め込むには`<%= %>`や`<% %>`で囲います。この2つの違いは「HTMLとして出力するか否か」です。if文で条件分岐されてtrueとなった方のみがHTMLとして出力されるので、もちろんif文自体はHTMLとして出力はしませんので`<% %>`を使います。
ここではRubyのコードでありdeviseが用意しているメソッドである`user_signed_in?`で、条件分岐しています。

次にログイン時にEmailを表示します。ログイン中のユーザーの情報を引き出せる`current_user`メソッドがdeviseに用意されているので、これにemailゲッターメソッドを掛け合わせて`current_user.email`とします。これでユーザーのEmailアドレスが表示できます。これもRubyのコードであり、これはHTMLとして出力するものなので、`<%= %>`で囲います。
次にログアウトのリンクを表示します。`link_to`はRailsに用意されているhelperというビューをシンプルに書くための機能で、他には`form_tag`などもありそれぞれHTMLのa要素、form要素に対応しています。`link_to`後の引数`'ログアウト'`はビューに表示される文字列をあらわし、次の`destroy_user_session_path`はログアウトへのパスですがここではURIではなくPrefixを使用しています。確認方法はURIと同じで`rails routes`をターミナルで打った結果をご覧ください。　次の`method: :delete`はVerbがgetでないときに必要なものですが、ここでは説明は省きます。ログアウト用のビューはなくこのリンクをクリックするとログアウト処理だけなされ、ルート画面に遷移します。
先の新規登録とログインも同様です。

以上で完成です。

# まとめ
慣れれば10分かからないレベルの作業であると思います。
いろいろ考え方があると思いますが、私はこの時点でGitの監視を始めて、デプロイもこの時点で済ませてしまうべきであると思います。

[完成品GitHub](https://github.com/annaPanda8170/minimum_rails_application)

# この記事の続編
以下の5つどれでもすぐに始められます。

・　[ツイッター風Railsアプリをデプロイする（前編：unicornのみで取り急ぎ繋げよう）](https://qiita.com/annaPanda8170/items/88c601833e60fc4ddb40)
　　※"ツイッター風Railsアプリを"とありますが、この「超最低限のRailsアプリ」でもやり方は全く同じです。

・　[超最低限のRailsアプリをテストする（モデル編）](https://qiita.com/annaPanda8170/items/955d2db7058a6928f281)

・[『メッセージを投稿』できる最低限のRailsアプリを丁寧に作る(これで初心者完全卒業!)](https://qiita.com/annaPanda8170/items/c042d533a3afb28213ee)

・[『2ページ遷移して会員登録』できる最低限のRailsアプリを丁寧に作る（deviseをウィザード形式に拡張）](https://qiita.com/annaPanda8170/items/c4e1052d254518d96cfa)

・[『非同期でのメッセージ投稿』が理解できる最低限のRailsアプリを丁寧に作る（Ajax苦手の自分とお別れしよう）](https://qiita.com/annaPanda8170/items/8c014d6c73cb14ee61cb)
# おまけ

##⑤コントローラ名の変更
今回取り急ぎ作ったコントローラ名がこれから作るアプリにそぐわない場合は変更します。
私は今`UsersController`としていますが、`XxxxsController`にしてみたいと思います。

コントローラ名の変更は、一度消去して新しく作ることが基本です。つまり変更はしないということです。プロジェクト内のファイルの依存関係を完全に把握しているなら問題ないかもしれませんが、そうでないと思わぬ落とし穴が待っています。
今回は必要なファイルの内容をコピペで避難させておき、消去して、新しく作って、コピペして、整えるという方針で行きます。

消去するには、ターミナルで`rails g controller <コントローラ名>`の`g`を`d`に変えただけの`rails d controller <コントローラ名>`を打ちます。
何が消えるかというと`rails g controller <コントローラ名>`で作られたものと同じで、私の場合、

`app/controllers/users_controller.rb`と
`app/views/users/`に入っている全てのビューファイルと

あとは今回触っていない
`test/controllers/users_controller_test.rb`と
`app/helpers/users_helper.rb`と
`app/assets/javascripts/users.coffee`と
`app/assets/stylesheets/users.scss`
です。

あ、実は`app/controllers/users_controller.rb`も今回触れていないですね。
なので避難させるべきは`app/views/users/index.html.erb`のみです。どこかにコピペしておきましょう。
避難が済んだら、

```bash:Terminal
$ rails d controller users
```

続いて

```bash:Terminal
$ rails g controller xxxxs index
```

して、`app/views/xxxxs/index.html.erb`にコピペを済ませて、ルーティングを整えます。
上のまま`rails g controller xxxxs index`としたか、`index`なしで`rails g controller xxxxs`としたかによってルーティングの状況が異なってきますが、最終的に

```ruby:config/routes.rb
Rails.application.routes.draw do
  devise_for :users
  root 'xxxxs#index'
  get 'xxxxs/index'
end
```

となっていれば問題ありません。ちなみに並べ順は任意です。
これで`localhost:3000/`と念のために`localhost:3000/xxxxs/index`にアクセスしてみて、何も変わってなければ完成です。

え？それだけじゃ確認があまい？

そうですね。

`localhost:3000/users/index`にアクセスして<b>エラーになることを</b>確認出来て初めて完成ですね。