この記事の基本的な方針
0からアプリケーションを立ち上げるとき、どういう手順で行うでしょうか?
考えれば考えるほどやりたいことややらなければならないことが溢れてくると思いますが、
「全てのアプリケーションに共通した超最低限のものをまず組む」、そして「必要に応じてどんどん拡張してゆく」が正しい手順です。
では全てのアプリケーションに共通した超最低限のものとはなんでしょうか?
それはログイン機能です。
ここでは、「新規登録画面」・「ログイン画面」・「インデックス画面」のたった3画面のアプリを作ります。インデックス画面は、ログイン状態であれば「自身のemailアドレス」と「ログアウトのリンク」が表示され、非ログイン状態であれば「新規登録のリンク」と「ログインのリンク」が表示されます。以下が完成です。
【TOP画面(ログイン前)】 【TOP画面(ログイン後)】
【登録画面】
【ログイン画面】
想定する読み手
既に一度Railsアプリをチュートリアルやスクール等で作ったことがある方を想定しております。
Mac使用で、パソコンの環境構築は完了していることが前提です。
具体的なコーディング手順
①アプリを立ち上げる
まずターミナルを開きcd
コマンドを使い、アプリを立ち上げたい場所に移動します。
今回はデスクトップに作ります。
$ cd #ルートディレクトリに移動する
$ cd Desktop #デスクトップに移動する
アプリを立ち上げるためにrails new
をするのですが、まずRailsのバージョンと使用するデータベースを決めます。
バージョンについては指定する必要がなければ記載する必要はありません。記載しなければ自身のパソコンに入っているRailsに基づいて一番最新のものになります。
指定する必要があれば、どのバージョンを指定できるかを確認します。以下をターミナルで打ちます。
$ gem list
するとパソコンに入っているgemのリスト一覧が出てくるのでRailsを探します。探すのが面倒であればgem list -e rails
とすればRailsのみが出てきます。
私のパソコンだと
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にすることにし、
$ rails _5.2.3_ new <名前> -d myspl
します。
あ、-d mysql
はMySQLをデータベースとして使用しますよって意味です。なにも書かないとsqlite3
っていうのになるそうですが、私はMySQLしか使ったことないのでよくわかりません。もしrails new
する時点でデータベースを指定していなかったとしてもconfig/database.yml
の中を書き換えてgemをインストールすればMySQLを使えます。
これでアプリが立ち上げられたと思うので、そのアプリのルートディレクトリに移動します。
$ cd <名前>
データベースを作ります。
$ rails db:create
(中身が空であってもこの時点でデータベースは作っておかないと、ブラウザでアクセスした時にActiveRecord::NoDatabaseError
になってしまいます。)
そして
rails s
でサーバーを立ち上げて、ブラウザでlocalhost:3000/
にアクセスすると
これが表示されます。
(ところでバージョン指定したのに5.2.4.1
になってしまっているのはなぜかわかりません。もう少し離れたバージョンだとその通りになります。)
(追記:この件についてコメントをいただきましたので、ここで迷っておられる方は下のコメント欄をご覧くださいませ。)
②インデックス画面を表示できるようにする
コントローラを作ります。
$ rails g controller <名前>
名前は自由ですが一番関連のある(データベースの)テーブル名の複数形にするのが一般的です。
このコマンドでコントローラとビューに関するファイルが作られます。
$ rails g controller <名前> index
のように名前の後にアクションを並べれば、そのアクション用のhtml.erbファイルが作られ、ルーティングとコントローラファイルに必要なことが追記されます。アクションはもちろん複数並べてよく、コンマ無しで隙間だけ開けて並べていきます。
ここでエディタを起動します。
まずルーティングを設定をします。上でアクション名を並べていればすでに書かれています。
get "コントローラ名/index"
取り急ぎ、適当にビューを書きます。
<div>こんにちは</div>
ここでブラウザでlocalhost:3000/コントローラ名/index
にアクセスすれば、「こんにちは」が見れるはずです。
通常メインのindex画面をルート画面とするので
root "コントローラ名#index"
を追記しておきます。localhost:3000
でもアクセスできるようになります。
ルーティングの書き方はいくつかあり、get "名前", to: "コントローラ名#index"
とすればlocalhost:3000/名前
でアクセスできるようになりますし、resources
を使った方法もあります。
え?エラーになりますか?
/
と#
を間違えていませんか?
,
を忘れていませんか?
③ログイン機能を作る
ログイン機能は自作することもできますが、deviseというgemを使うことが極めて一般的であるのでこれを今回は使用します。
deviseをインストールします。
gem 'devise'
こちらを追記し、ターミナルで
$ bundle install
をし、サーバーをcontrol + c
で停止しrails s
で再び起動します。
サーバーの再起動忘れが原因のエラーは世界中で大量発生しているので注意しましょう(笑)
そしてdeviseを使い始めるにはターミナルで
rails g devise:install
をする必要があります。これでconfigディレクトリにファイルができたので、またサーバの再起動の必要があります。
さらに、
rails g devise <モデル名>
をすれば必要ないくつかのファイルが作られます。この時のモデル名はなんでもいいのですが、userとするのが一般的です。deviseに関するあらゆる記事がこの名前をuserにしたことを前提としたものであり、これ以外にすると思わぬエラーが出る可能性があります。例えば名前をxxxとした場合、普通ログイン中かを確認するメソッドがuser_signed_in?
であるところ、xxx_signed_in?
となったりします。
続いて、上のrails g devise <モデル名>
でマイグレーションファイルも作られているので、
$ rails db:migrate
します。これでデータベースにユーザー情報用のテーブルが作られます。
deviseはデフォルトではEmailとPasswordで登録する仕様になっています。逆に、このままの仕様でよければビューもルーティングの記述もコントローラもすでにrails g devise <モデル名>
で準備されています。
ビューとコントローラは隠れているので現時点では見れません。EmailやPassword以外を含めて登録する場合やビューやコントローラを編集する場合は別の手続きが必要です。
さてこの時点でURIをブラウザに直接打ち込めば新規登録画面とログイン画面が表示される段階まで来ています。
さてではURIは何と打ち込めばいいのでしょうか?まずはもちろんconfig/routes.rb
を見にいきます。上のrails g devise <名前>
で自動的にdevise_for :users
が書き込まれていますがこれでは何と打ち込めばいいかわかりません。
ので、ターミナルで
$ rails routes
をしてみます。
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
とブラウザに打てば、
このように表示されます。localhost:3000/users/sign_in
も同様に表示されるはずです。
ここで適当に新規登録をしてみて、成功すると自動的にログイン状態になり、『こんにちは』のTOP画面に遷移します。これもログインしたらルート画面に遷移しますというdeviseのデフォルトの機能です。もし上でconfig/routes.rb
にroot "コントローラ名#index"
を設定していなければ、もちろん
が表示されることとなります。
これでログイン機能完成です。
ちなみにログイン機能はdeviseを使わなくても、ユーザー情報をformで入力させそれをデータベースに保存できるよにし、さらにログイン時にsession変数にそのユーザーのユニークな情報(普通はユーザーIDかEmail)を代入し、ログアウト時にsession変数を空にする処理をすれば概ね実装できます。ただ、その後にパスワードを暗号化したり色々必要なことが出てくるので、deviseを使ってしまうことをおすすめします。
④TOP画面作成
さてあとは今『こんにちは』になっている、TOP画面を作れば完成です。
TOP画面は、
ログイン状態であれば、そのユーザーのEmailアドレスとログアウトへのリンク、
非ログイン状態であれば、新規登録へのリンクとログインへのリンクが表示されるようにします。
全体を一度に載せてみます。
<% 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の監視を始めて、デプロイもこの時点で済ませてしまうべきであると思います。
この記事の続編
以下の5つどれでもすぐに始められます。
・ ツイッター風Railsアプリをデプロイする(前編:unicornのみで取り急ぎ繋げよう)
※"ツイッター風Railsアプリを"とありますが、この「超最低限のRailsアプリ」でもやり方は全く同じです。
・『メッセージを投稿』できる最低限のRailsアプリを丁寧に作る(これで初心者完全卒業!)
・『2ページ遷移して会員登録』できる最低限のRailsアプリを丁寧に作る(deviseをウィザード形式に拡張)
・『非同期でのメッセージ投稿』が理解できる最低限のRailsアプリを丁寧に作る(Ajax苦手の自分とお別れしよう)
おまけ
##⑤コントローラ名の変更
今回取り急ぎ作ったコントローラ名がこれから作るアプリにそぐわない場合は変更します。
私は今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
のみです。どこかにコピペしておきましょう。
避難が済んだら、
$ rails d controller users
続いて
$ rails g controller xxxxs index
して、app/views/xxxxs/index.html.erb
にコピペを済ませて、ルーティングを整えます。
上のままrails g controller xxxxs index
としたか、index
なしでrails g controller xxxxs
としたかによってルーティングの状況が異なってきますが、最終的に
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
にアクセスしてエラーになることを確認出来て初めて完成ですね。