はじめに
第8回目です。前回、Userモデルを作り上げユーザー詳細ページを作成するところまでいきました。
今回は、ユーザーをUIから登録すべくSign upページを作っていきたいと思います。
いままではRailsコンソールからモデルを操作してユーザーを作成していましたが、今回からはMVCを連携させてユーザーを作成させるようにします。
前回のソースコード
前回のソースコードはこちらに格納してます。今回のハンズオンからやりたい場合はこちらからダウンロードしてください。
Sign upページの作成
今回はSign upページでユーザーのname
、email
、password
を入力してもらい、登録完了後そのユーザーのユーザー詳細ページに遷移させます。
まずは、このアプリを実現するために必要なファイルや設定を作成していきます。
今回、Sign upページにアクセスするためのRouting、Action、Viewと、実際にUserをDBに登録するRouting、Actionが必要になります。
Scaffoldを思い出してみてください。
あの時、新規にユーザーを作成するには/users/new
のページにアクセスしており、new
アクションがありました。
そこで登録ボタンを押すと、/users
のURLにPOSTメソッドでリクエストが飛びcreate
アクションがDBにユーザーを保存していました。
では、これらの設定を元にRouting、Action、Viewをコーディングしていきましょう!
Routing
まず、users#new
、users#create
へのルーティングを作成します。
しかし、Sign upページと呼んでいるのですから/users/new
のようなURLでは少しカッコつきません。
今回は/sign_up
にGETリクエストしたときにusers#new
にルーティングされるように定義していきましょう。
users#create
へのルーティングも/sign_up
にPOSTリクエストしたときに定義します。
Rails.application.routes.draw do
root 'static_pages#home'
+
+ get '/sign_up', to: 'users#new', as: :sign_up
+ post '/sign_up', to: 'users#create', as: :create_user
resources :users, only: [:show]
end
基本となるルーティング定義の書き方は以下の通りです。
[method] '[path]', to: '[controller_name]#[action_name]', as: '[route_name]'
このコーディングで
「path
にmethod
でリクエストされた場合、controller_name
コントローラーのaction_name
アクションにルーティングする。アプリのコードとしてroute_name
_pathと表現された場合は、このルーティングを表すことと定義する。」
ということをRailsアプリケーションに定義立てています。
route_name
はシンボル(:sign_up
のように:
を頭につけてる文字)で書いてます。シンボルは複数あっては困るものなどに使用するそうです(参考: 「Rubyのシンボルと文字列の違い | UX MILK)。
ルートの名前も重複しては困りますので、シンボルを使っています。
ルーティングの設定はこれで完了です。次はコントローラーに新しくアクションを用意しましょう。
Action
次にUserコントローラーにnew
アクションを追加します。
class UsersController < ApplicationController
def show
@user = User.find(params[:id])
end
+
+ def new
+ @user = User.new
+ end
+
+ def create
+ end
end
new
アクションでは、インスタンス変数@user
にUser.new
を代入しています。
これはView側でUserモデルを扱ってフォームを作っていくために空のモデルが必要なのです。
詳しくはView側で説明しますので、ひとまずそのままコピペでお願いします。
create
アクションはとりあえず定義だけしておきます。処理はのちのち。
View
ではでは、Viewファイルを作っていきます。
new
アクションでrenderされるViewなのでnew.html.erb
ファイルを作成します。
$ docker-compose up -d
$ docker-compose exec web ash
# touch app/views/users/new.html.erb
<div class="container">
<h1 class="my-5">Sign up</h1>
<%= form_with model: @user, url: create_user_path, local: true do |form| %>
<div class="form-group">
<%= form.label :name %>
<%= form.text_field :name, class: "form-control" %>
</div>
<div class="form-group">
<%= form.label :email %>
<%= form.text_field :email, class: "form-control" %>
</div>
<div class="form-group">
<%= form.label :password %>
<%= form.password_field :password, class: "form-control" %>
</div>
<div class="form-group mt-5">
<%= form.submit "Sign up!", class: "form-control btn btn-primary" %>
</div>
<% end %>
</div>
構文自体はそこまで難しくないですね。http://localhost:3000/sign_up
にアクセスしてみましょう。
なかなかぽいページになったんじゃないでしょうか?
password_confirmation
は使わないことにしました。「登録フォームにおけるパスワード確認用の入力欄は必要か | UX MILK」の記事を参考にしまして。
いくつかrubyコードが埋め込まれているので説明していきますね。
form_with
こういうのをビューヘルパー(View helper)っていいます。
『form_with』ヘルパーはform
タグを生成してくれるヘルパーです。
model
をオプションに指定することでそのモデルオブジェクトのためのフォームを作ってくれるようになります。上のコードのようにブロック形式でform
変数を使うことで、例えばform.input_field :name
とするだけで@user
のname
属性に関するinputフィールドを作ってくれるようになるので、これは超便利です。
url
オプションはフォームの送信先を定義します。create_user_path
はroutes.rb
でusers#create
へのルーティングにつけた名前ですね。
このようにコーディングすることでcreate
アクションにフォームを送信できるようになります。
また、local: true
オプションも付けています。form_with
ヘルパーではデフォルトでAjax通信でフォームをポストします。つまり、画面遷移なしでフォームをリクエストするんです。これはこれで便利な場面もあって今時な感じなんですが、今回はユーザーの新規作成が成功したらそのユーザーのマイページに画面遷移させたいので、local: true
オプションでAjax通信をオフにしています。
ちなみに『Ajax』は『エイジャックス』または『アジャックス』と読むそうです。僕は『エイジャックス』って読んでます。
今回のform_with
は実際にクライアントに返却される場合は以下のように変換されて返却されています。
<%= form_with model: @user, url: create_user_path, local: true do |form| %>
...
<% end %>
↓
<form action="/sign_up" accept-charset="UTF-8" method="post">
<input type="hidden" name="authenticity_token" value="xxxxxxxxxx">
...
</form>
authenticity_token
が第3回の時に少し触れた、CSRFトークンですね。XSSを防いでくれるやつです。
label
label
はラベルを付けてくれるやつです。ページで『お名前』とか『メールアドレス』と出ているやつのことです。
<%= form.label :name %>
↓
<label for="user_name">お名前</label>
text_field
text_field
はinput type="text"
タグでテキストフィールドを作り出してくれます。
使い方も簡単で、text_field [attribute_name], [options]
なだけです。
今回はBootstrapのform-control
classをオプションで付けてあげています。
<%= form.text_field :name, class: "form-control" %>
↓
<input class="form-control" type="text" name="user[name]" id="user_name">
name
やid
も勝手に付けてくれているのがいいですよね。
ここでid="user_name"
を付与してくれているので、label
のfor="user_name"
と紐付けができるようになっています。
password_field
password
を入力するフォームのところではpassword_field
を使いました。
これはtext_field
と似ていますが、input type="password"
タグのフィールドを作ってくれるやつです。
<%= form.password_field :password, class: "form-control" %>
↓
<input class="form-control" type="password" name="user[password]" id="user_password">
input type="password"
はパスワード用の入力フィールドを作り出せるので、入力した文字が『●』でマスク化されるようになります。
submit
submit
タグはフォーム送信用のボタンを作ってくれるタグです。input type="submit"
を作ってくれるんですね。
<%= form.submit "Sign up!", class: "form-control btn btn-primary" %>
↓
<input type="submit" name="commit" value="Sign up!" class="form-control btn btn-primary" data-disable-with="Sign up!">
HTMLの方にあるdata-disable-with
はダブルクリック抑止のためのパラメータですね。RailsのERBを使えばこういった必要だけどついつい忘れてしまいがちなHTMLオプションも自動で付与してくれるので積極的に利用するといいと思います。
これ以外にもいろいろなヘルパーが用意されているので、HTMLのあのタグはどうやって書けばいいのか、と思った時は直接HTMLタグを書くのではなく一度Railsでの書き方をググってみるといいでしょう!
これでViewがいい感じに作れました。次は「Sign up!」ボタンを押した時の処理をコーディングしていきます。
Createアクションをコーディング
ここまででnew.html.erb
のフォームからcreate
アクションにフォームをリクエストできるようになりました。
ここからはcreate
アクションでリクエストされたフォームのデータからDBにUserを登録できるようにします。
では、先ほど"とりあえず"作ったcreate
アクションをコーディングしていきます。
class UsersController < ApplicationController
def show
@user = User.find(params[:id])
end
def new
@user = User.new
end
def create
+ @user = User.new(user_params)
+ if @user.save
+ redirect_to @user
+ else
+ render :new
+ end
end
+
+ private
+ def user_params
+ params.require(:user).permit(:name, :email, :password)
+ end
end
はい。初見だとけっこう複雑に見えるんじゃないかなーと思います。
1行ずつみていきましょう。
@user = User.new(user_params)
まず、@user
にUser.new(user_params)
を代入しています。
user_params
とは何でしょう?
private
def user_params
params.require(:user).permit(:name, :email, :password)
end
user_params
はここで定義されている関数ですね。
params.require(:user).permit(:name, :email, :password)
の部分は『ストロングパラメーター(Strong parameter)』と呼ばれています。Railsが用意しているこのストロングパラメーターは意図しないデータのPOSTを防いでくれます。
params.require([model_name]).permit([attribute_names])
これでリクエスト内のパラメーター(params
)からmodel_name
モデルに紐づくデータのみを抽出し、さらにその中からattribute_names
に指定されているデータのみを抽出して返却します。
それ以外のデータはドロップします。これによってユーザーのいたずらで意図しないデータが作られてしまうことを防ぐということです。
例えばモデルにはこっそりadmin
フラグみたいなものがあって1
のユーザーはなんでもできちゃう権限を持っているとします。いたずらっ子のユーザーがそれに気づいてSign upページにdeveloper toolsとかを使ってadmin=1
のフォームを追加してきたりしたとします。ここでストロングパラメーターを使っていない場合はadmin=1
でユーザーが作成されてしまいアプリが乗っ取られてしまう、みたいなことが起きちゃうんですね。
ストロングパラメーターはそういった意図しないフォームからのリクエストを無視するようになるので、安全なアプリケーションの作成に不可欠なものなのです。
今回はUser
モデルのname
、email
、password
以外のデータは無視することを定義しています。
また、この関数はprivate
より下に書かれています。これはクラス内からのみアクセスできる関数であることを定義しています。
さて、ここまでで@user
にuser_params
で抽出されたデータが初期値として設定されたUser
モデルオブジェクトが代入される、ということになります。
if @user.save
redirect_to @user
else
render :new
end
次は、この@user
をsave
して条件分岐しています。ModelのCRUDの時にも話がでてきましたがsave
メソッドはバリデーションを通りデータをDBに保存できた場合true
を、バリデーションに引っかかった場合false
を返却します。
その結果を元にtrue
の場合はredirect_to @user
、false
の場合はrender :new
が実行されます。
redirect_to @user
redirect_to
メソッドは引数にGET
メソッドでリダイレクトします。
引数には@user
を指定してます。これは、user_path(@user)
と同義です。user_path
はshow
メソッドにつけられている名前です。@user
には今DB保存が成功したUserモデルオブジェクトが入っていますので、今保存したユーザーのユーザー詳細ページに遷移させています。
render :new
false
の場合はこちらが実行されます。
render
メソッドは指定したアクションのViewファイルをレンダリングするメソッドです。(いろいろと使い方はありますが、今回はこんな説明で)
通常アクションは自分の名前と同じViewファイルをレンダリングするようになっていますが、render
メソッドを使うことで別のアクションのViewファイルをレンダリングするようにすることもできます。
この場合は、new
アクションのViewファイルがレンダリングされます。さらに@user
には今false
になったUserモデルオブジェクトが入った状態でnew.html.erb
に引き渡されます。
そのため、レンダリングされたとしても今入力してた属性データは再表示されるはずだし、@user.errors
の中にはsave
に失敗した理由も残っているわけです。new.html.erb
側を少し更新すればエラーメッセージを表示することもできます。
new.html.erb
でエラーメッセージを表示できるように更新
ということでnew.html.erb
を更新して、save
でエラーが発生した場合はerrors.full_messages
が表示されるようにしてみましょう。
<div class="container">
<h1 class="my-5">Sign up</h1>
+
+ <% if @user.errors.any? %>
+ <div class="alert alert-danger">
+ <ul class="mb-0">
+ <% @user.errors.full_messages.each do |msg| %>
+ <li><%= msg %></li>
+ <% end %>
+ </ul>
+ </div>
+ <% end %>
<%= form_with model: @user, url: create_user_path, local: true do |form| %>
...
</div>
これも少し説明します。
<% if @user.errors.any? %>
...
<% end %>
まず一番外側を囲っている部分です。
any?
メソッドは対象が"空"でないかどうかを検証して「空でない」場合にtrue
を返します。
今回は@user.errors
に対してany?
メソッドを適用しているので、validationによるエラーがある場合にtrue
になります。
<div class="alert alert-danger">
<ul class="mb-0">
<% @user.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
@user.errors.any?
がtrue
の場合にはこの部分が表示されることになります。
ul
タグはリストを表示するためのタグですね。li
タグがul
タグのアイテムとして『・』を頭につけた箇条書き形式で表示されるようになっています。
li
タグは以下のコードに囲まれています。
<% @user.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
@user.errors.full_messages
はバリデーションの回でも使ったので覚えている人が多いと思います。
バリデーションでエラーが起きた時にユーザーにそのまま見せれるようなエラーメッセージが配列で格納されていたやつです。
それをeach
でひとつずつ取り出し、msg
に格納して、@user.errors.full_messages
がなくなるまでブロックの中の処理を繰り返します。
ブロックの中の処理は<li><%= msg %></li>
だけなので、ここで@user.errors.full_messages
のエラーメッセージを一つずつli
タグで囲って表示してあげていますね。
結果として、全てのエラーメッセージが箇条書きの形式で表示されるようになると期待できます。
ここまでできたら実際に動作確認をしてみましょう!
動作確認(エラー編)
まずはエラーの場合の動作確認をしてみます。
以前Userモデルのバリデーションを確認したときのように、いくつかのエラーケースでエラーメッセージが表示されるかどうかを確認していきましょう。
存在性チェック
Userモデルではname
、email
、password
全てが入力必須(presence
)な項目です。
何も入力していなければエラーになるはず。
実際に何も入力せずに「Sign up!」ボタンを選択したページがこちらです。
「お名前」「メールアドレス」「パスワード」について、それぞれエラーが出ていてUserの作成がうまくいかなかったことがわかりますね。
文字数チェック
name
とemail
にはそれぞれ最大50文字、255文字の制限を設けていました。
それ以上の文字数でエラーになるか確認してみましょう。
51文字と256文字の文字列は↓をお使いください。
Name
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Email
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb@sample.com
文字数制限のエラーが出ていますね。
ちなみに「パスワード」には適当にパスワードを入力して「Sign up!」ボタンを選択したので「パスワード」に関するエラーは出ていないです。「パスワード」はtype="password"
のフィールドを使っているので、エラー時に元の値が反映されないようになっているんですね。
フォーマットチェック
email
にはフォーマットの検証もいれていました。例えば「@」がない場合はメールアドレスとしておかしいのでちゃんとエラーが返却されるか確認してみましょう。
ちゃんとエラーになっていますね。
重複チェック
最後にemail
の重複チェックもみてみましょう。
とりあえずjohn@sample.com
のemail
をもつユーザーをRailsコンソールから作っておきます。
# rails c
> User.create(name: "John Smith", email: "john@sample.com", password: "password")
(0.3ms) BEGIN
User Exists? (7.3ms) SELECT 1 AS one FROM "users" WHERE LOWER("users"."email") = LOWER($1) LIMIT $2 [["email", "john@sample.com"], ["LIMIT", 1]]
User Create (17.4ms) INSERT INTO "users" ("name", "email", "created_at", "updated_at", "password_digest") VALUES ($1, $2, $3, $4, $5) RETURNING "id" [["name", "John Smith"], ["email", "john@sample.com"], ["created_at", "2020-03-09 19:22:14.408777"], ["updated_at", "2020-03-09 19:22:14.408777"], ["password_digest", "$2a$12$kGv3a06MmAJ.XapqOHTBDeAiRoPUNBse7R79n5f8WA/envU00qkq."]]
(3.8ms) COMMIT
=> #<User:0x0000558d40945160
id: 1,
name: "John Smith",
email: "john@sample.com",
created_at: Mon, 09 Mar 2020 19:22:14 JST +09:00,
updated_at: Mon, 09 Mar 2020 19:22:14 JST +09:00,
password_digest: [FILTERED]>
ユーザーを作ったので、同じメールアドレスを大文字とかにしてもエラーになるかを確認してみましょう。
ここまでチェックすれば、バリデーションはちゃんと効いていて、バリデーションエラーが起きた時のエラーハンドリングも正常に動作していることが確認できましたね。
動作確認(正常編)
ではいよいよユーザーを実際にUIから作ってみましょう。
今回は以下のユーザーを作ってみます。
name: Taro Tanaka
email: taro@sample.com
password: taro1234
ユーザー詳細ページに遷移しましたね!さらに今入力したユーザー情報もちゃんと表示されています!
Welcomeメッセージを表示する
ユーザーが作成されて、ユーザー詳細ページにも遷移できたのですが何か物足りないですね。
そうだ、Welcomeメッセージがないんだ。
ユーザー詳細ページは、Welcomeページというわけではないので今のまま装飾していけばいいのですが、会員登録した時に限ってでも「ようこそ!」みたいなメッセージがほしいですよね。
こういう一時的にページにメッセージを表示したいときに使えるRailsの機能としてflash
があります。
flash
はControllerで設定してあげます。今回はcreate
アクションでsave
に成功した時に表示されるようにしてみましょう。
create
アクションを通ってshow.html.erb
が表示された場合はWelcomeメッセージが表示されますが、通常show.html.erb
が表示される場合はcreate
アクションは通らずshow
アクションだけを通るので、例えばリロードすればメッセージが消えるという寸法です。
...
def create
@user = User.new(user_params)
if @user.save
+ flash[:success] = "サインアップありがとう!"
redirect_to user_path(@user)
else
render :new
end
end
...
Controller側の設定はこんな感じです。flash
に[:success]
のような形でメッセージのkey
を定義して= 文字列
の形でvalue
を与えます。
View側でこれを受け取って、flash
がある場合だけ表示するように、show.html.erb
も更新しましょう。
<div class="container my-5">
+ <% flash.each do |msg_type, msg| %>
+ <div class="alert alert-<%= msg_type %>"><%= msg %></div>
+ <% end %>
<%= @user.name %>
<br>
<%= @user.email %>
</div>
今回はflash[:success] = "サインアップありがとう!"
と定義しているので、msg_type
にsuccess
が、msg
にサインアップありがとう!
が格納されます。
alert-<%= msg_type %>
はalert-success
となるわけですね。Bootstrapでalert-success
のCSSが用意されているのでそれを適用するためにflash
のkeyをsuccess
にしていたわけです。
おんなじようにエラー系のメッセージにしたい場合はdanger
にしてあげたりするとViewファイルをいじらなくてもエラーっぽいCSSを適用することができます。
では実際に試してみましょう。
次は花子さんを作ってみます。http://localhost:3000/sign_up
にアクセスして以下のデータで登録してみましょう。
Name: Hanako Yamada
Email: hanako@sample.com
Password: hanako1234
この状態でリロードしてみてください。
メッセージが消えましたね。期待通りの動作です。
パスワードの表示非表示を制御する
あとそうだ。先ほどUX的にpassword_confirmation
は使いませんという話をしました。
しかし、今のままではパスワードが非表示しか対応していないので、ユーザーは自分の思ったパスワードが正しく入力できているか確認できません。
ただ、周りから見えないようにするのが目的でマスク化しているので、常に平文にすることもUX的によろしくないでしょう。
ということで、「パスワードを表示する」チェックボックスを用意して、チェックが入っている間だけ表示されるようにしようと思います。
まず、new.html.erb
にチェックボックスを追加します。
今回は@user
に紐づかないフォーム要素になるのでcheck_box_tag
を利用します。これはinput type="check_box"
タグを作ってくれるやつです。
...
<div class="form-group">
<%= form.label :password %>
<%= form.password_field :password, class: "form-control" %>
</div>
+ <div class="form-check">
+ <%= check_box_tag :visible_password, :visible, false, class: "form-check-input" %>
+ <%= label_tag :visible_password, "パスワードを表示する" %>
+ </div>
<div class="form-group mt-5">
<%= form.submit "Sign up!", class: "form-control btn btn-primary" %>
</div>
...
↓
...
<div class="form-group">
<label for="user_password">パスワード</label>
<input class="form-control" type="password" name="user[password]" id="user_password" />
</div>
<div class="form-check">
<input type="checkbox" name="visible_password" id="visible_password" value="visible" class="form-check-input" />
<label for="visible_password">パスワードを表示する</label>
</div>
<div class="form-group mt-5">
<input type="submit" name="commit" value="Sign up!" class="form-control btn btn-primary" data-disable-with="Sign up!" />
</div>
...
ただ今のままではただのチェックボックスにチェックを入れたり外したりできるだけです。
このチェックボックスの状態に合わせて「パスワード」のフィールドをマスク化したりマスク解除したりしていきましょう。
どうやるかというと、今マスク化されているのはinput
のtype
がpassword
になっているからです。他のinput
のフィールドは普通に文字が見えていますが、これはtype
がtext
になっているからです。
なので、チェックボックスの状態に合わせて、チェックが入っている場合はtype="text"
、チェックが入っていない場合はtype="password"
と切り替えることができれば、パスワードの表示非表示を制御できるはずです。
これを実装するには、フロントエンドで動作するjavascript(jQuery)を使います。
ごちゃごちゃするといけないので、application.js
ではなくファイルを追加してそちらでコーディングしていきましょう。
> quit
# touch app/javascript/packs/visible_password.js
$(function() {
$("#visible_password").change(function() {
type = "password"
if ($(this).prop("checked")) {
type = "text"
}
$("#user_password").attr("type", type)
})
})
まず、型として$(function() { ~ })
で囲みまして、{}
の中に処理をコーディングしていきます。
$("#visible_password").change(function() {
...
})
最初に$("#visible_password").change
と書きました。これはid
がvisible_password
のinput
タグに変化が起きたときに処理されることを意味しています。こういった何かが起こったときに処理が実行されることを『トリガー』とか『発火する』とか言うので覚えておきましょう!
今回の場合はid
がvisible_password
のinput
の変化をトリガーにする、とか、変化が起きた時に発火する、みたいな表現をするってことです。
type = "password"
処理の中をみると、まず最初にtype = "password"
の変数定義をしていますね。
if ($(this).prop("checked")) {
type = "text"
}
その後、if ($(this).prop("checked"))
の条件分岐を書いています。
$(this)
はjQueryの特殊な書き方だと思いますが、トリガーの元になった要素のことです。
prop("checked")
はその要素のチェックボックスがチェックされているかを取得するメソッドなので、$(this).prop("checked")
はvisible_password
のチェックボックスにチェックが入っていればtrue
、そうでなければfalse
になります。
つまりif
文の部分は、「チェックボックスにチェックが入っていればtype
変数を"text"
に更新する」、ことが記述されています。
$("#user_password").attr("type", type)
最後に、$("#user_password")
、つまりid
がuser_password
の要素(パスワードのinput
タグ)にattr("type", type)
をしています。
attr
はその要素の属性を取得したり更新したりするメソッドです。引数が2つの場合は1つ目の引数の属性を2つ目の引数の値に更新します。今回の場合はid="user_password"
のtype
を変数type
に更新しています。
変数type
はデフォルトではpassword
、チェックボックスにチェックが入っている場合はtext
になるので、チェックボックスにチェックを入れるとパスワードが表示される仕組みです。
さて、実際に使えるようにするには、このファイルを読み込めるようにする必要があります。
このファイルはアプリケーションの全てのページで使うのではなく、Sign upページでのみ利用するようなファイルなので、new.html.erb
で読み込みを定義してあげます。
<div class="container">
...
</div>
+ <%= javascript_pack_tag 'visible_password' %>
Sign upページをリロードして試してみましょう!
チェックなし👆👇チェックあり
期待通りの動作になりましたね!
トップページからリンクさせる
最後にトップページの「Sign up now!」ボタンからSign upページにリンクを貼ってあげましょう。
<div class="jumbotron mb-0">
<div class="container text-center">
<h1>Welcome to Sample App.</h1>
<h2>Twitterみたいなアプリです。</h2>
- <%= link_to "Sign up now!", "#", class: "btn btn-lg btn-primary mt-5" %>
+ <%= link_to "Sign up now!", sign_up_path, class: "btn btn-lg btn-primary mt-5" %>
</div>
</div>
はい、これで完了です!#
をサインアップページへルーティングされている名前付きルートに変えただけです。
トップページ(http://localhost:3000/
)にアクセスして「Sign up now!」ボタンをクリックしてみましょう。ちゃんとSign upページに遷移するはずです。
後片付け
本日はここまでです!
いつものように、次回に向けてデータを消します。
# exit
$ docker-compose down
$ docker-compose run --rm web rails db:migrate:reset
DBコンテナが立ち上がった状態だと思うのでdownさせます。
$ docker-compose down
まとめ
今回は、サインアップページとユーザー登録機能を作っていきました。
今までと比べると少し複雑なControllerのコーディングをしましたね。バリデーションの結果に合わせてエラーメッセージを表示させてみたり、登録完了後のウェルカムメッセージを表示させたりしてみました。
また、jQueryを使ってパスワードの表示非表示をクライアントサイドで変更するコーディングもやってみました。
jQuery(javascript)はWebアプリケーションを作る上では欠かせない技術ですのでぜひ覚えてくださいね。
さて、今回はユーザー登録はできたものの、サインイン(ログイン)してそのユーザー独自の機能を提供する、ということはできていません。例えば、今のまま開発を進めてしまっては誰もが全てのユーザーの情報をみれてしまったり更新できてしまったりします。
そこで次回は、セッション管理をすることでサインイン機能を実装してみようと思います。
では、次回も乞うご期待!ここまでお読みいただきありがとうございました!
Next: コーディング未経験のPO/PdMのためのRails on Dockerハンズオン vol.9 - Sign in - - Qiita
本日のソースコード
Reference
- Ruby on Rails チュートリアル:実例を使って Rails を学ぼう
- 登録フォームにおけるパスワード確認用の入力欄は必要か | UX MILK
- Action Controller の概要 - Railsガイド
- jQuery 属性値を取得/設定/削除する(attr/removeAttr) | ITSakura
- jQueryでチェックボックスのチェック状態を取得する (jQuery + JavaScript プログラミング)