LoginSignup
60
90

More than 3 years have passed since last update.

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

Last updated at Posted at 2020-03-04

この記事の基本的な方針

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

【TOP画面(ログイン前)】     【TOP画面(ログイン後)】
a0.png a9.png
【登録画面】
a1.png
【ログイン画面】
a2.png

想定する読み手

既に一度Railsアプリをチュートリアルやスクール等で作ったことがある方を想定しております。
Mac使用で、パソコンの環境構築は完了していることが前提です。

具体的なコーディング手順

完成品GitHub

①アプリを立ち上げる

まずターミナルを開きcdコマンドを使い、アプリを立ち上げたい場所に移動します。
今回はデスクトップに作ります。

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

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

Terminal
$ gem list

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

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にすることにし、

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

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

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

Terminal
$ cd <名前>

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

Terminal
$ rails db:create

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

そして

Terminal
rails  s

でサーバーを立ち上げて、ブラウザでlocalhost:3000/にアクセスすると
rails new.jpg
これが表示されます。
(ところでバージョン指定したのに5.2.4.1になってしまっているのはなぜかわかりません。もう少し離れたバージョンだとその通りになります。)
(追記:この件についてコメントをいただきましたので、ここで迷っておられる方は下のコメント欄をご覧くださいませ。)

②インデックス画面を表示できるようにする

コントローラを作ります。

Terminal
$ rails g controller <名前>

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

Terminal
$ rails g controller <名前> index

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

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

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

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

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

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

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

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

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

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

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

③ログイン機能を作る

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

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

Gemfile
gem 'devise'

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

Terminal
$ bundle install

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

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

Terminal
rails g devise:install

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

Terminal
rails g devise <モデル名>

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

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

Terminal
$ rails db:migrate

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

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

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

Terminal
$ rails routes

をしてみます。

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とブラウザに打てば、
in.png
このように表示されます。localhost:3000/users/sign_inも同様に表示されるはずです。
ここで適当に新規登録をしてみて、成功すると自動的にログイン状態になり、『こんにちは』のTOP画面に遷移します。これもログインしたらルート画面に遷移しますというdeviseのデフォルトの機能です。もし上でconfig/routes.rbroot "コントローラ名#index"を設定していなければ、もちろん
rails new.jpg
が表示されることとなります。
これでログイン機能完成です。

ちなみにログイン機能は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

この記事の続編

以下の5つどれでもすぐに始められます。

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

・ 超最低限のRailsアプリをテストする(モデル編)

『メッセージを投稿』できる最低限のRailsアプリを丁寧に作る(これで初心者完全卒業!)

『2ページ遷移して会員登録』できる最低限のRailsアプリを丁寧に作る(deviseをウィザード形式に拡張)

『非同期でのメッセージ投稿』が理解できる最低限のRailsアプリを丁寧に作る(Ajax苦手の自分とお別れしよう)

おまけ

⑤コントローラ名の変更

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

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

消去するには、ターミナルでrails g controller <コントローラ名>gdに変えただけの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のみです。どこかにコピペしておきましょう。
避難が済んだら、

Terminal
$ rails d controller users

続いて

Terminal
$ rails g controller xxxxs index

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

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にアクセスしてエラーになることを確認出来て初めて完成ですね。

60
90
5

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
60
90