1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

コーディング未経験のPO/PdMのためのRails on Dockerハンズオン vol.8 - Sign up -

Last updated at Posted at 2020-02-26

はじめに

第8回目です。前回、Userモデルを作り上げユーザー詳細ページを作成するところまでいきました。
今回は、ユーザーをUIから登録すべくSign upページを作っていきたいと思います。

いままではRailsコンソールからモデルを操作してユーザーを作成していましたが、今回からはMVCを連携させてユーザーを作成させるようにします。

前回のソースコード

前回のソースコードはこちらに格納してます。今回のハンズオンからやりたい場合はこちらからダウンロードしてください。

Sign upページの作成

今回はSign upページでユーザーのnameemailpasswordを入力してもらい、登録完了後そのユーザーのユーザー詳細ページに遷移させます。
まずは、このアプリを実現するために必要なファイルや設定を作成していきます。

今回、Sign upページにアクセスするためのRouting、Action、Viewと、実際にUserをDBに登録するRouting、Actionが必要になります。

Scaffoldを思い出してみてください。
あの時、新規にユーザーを作成するには/users/newのページにアクセスしており、newアクションがありました。
そこで登録ボタンを押すと、/usersのURLにPOSTメソッドでリクエストが飛びcreateアクションがDBにユーザーを保存していました。

では、これらの設定を元にRouting、Action、Viewをコーディングしていきましょう!

Routing

まず、users#newusers#createへのルーティングを作成します。
しかし、Sign upページと呼んでいるのですから/users/newのようなURLでは少しカッコつきません。
今回は/sign_upにGETリクエストしたときにusers#newにルーティングされるように定義していきましょう。
users#createへのルーティングも/sign_upにPOSTリクエストしたときに定義します。

config/routes.rb
  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]'

このコーディングで
pathmethodでリクエストされた場合、controller_nameコントローラーのaction_nameアクションにルーティングする。アプリのコードとしてroute_name_pathと表現された場合は、このルーティングを表すことと定義する。」
ということをRailsアプリケーションに定義立てています。

route_nameはシンボル(:sign_upのように:を頭につけてる文字)で書いてます。シンボルは複数あっては困るものなどに使用するそうです(参考: 「Rubyのシンボルと文字列の違い | UX MILK)。
ルートの名前も重複しては困りますので、シンボルを使っています。

ルーティングの設定はこれで完了です。次はコントローラーに新しくアクションを用意しましょう。

Action

次にUserコントローラーにnewアクションを追加します。

app/controllers/users_controller.rb
  class UsersController < ApplicationController
    def show
      @user = User.find(params[:id])
    end
+
+   def new
+     @user = User.new
+   end
+
+   def create
+   end
end

newアクションでは、インスタンス変数@userUser.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
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にアクセスしてみましょう。
image.png
なかなかぽいページになったんじゃないでしょうか?
password_confirmationは使わないことにしました。「登録フォームにおけるパスワード確認用の入力欄は必要か | UX MILK」の記事を参考にしまして。
いくつかrubyコードが埋め込まれているので説明していきますね。

form_with

こういうのをビューヘルパー(View helper)っていいます。
form_with』ヘルパーはformタグを生成してくれるヘルパーです。
modelをオプションに指定することでそのモデルオブジェクトのためのフォームを作ってくれるようになります。上のコードのようにブロック形式でform変数を使うことで、例えばform.input_field :nameとするだけで@username属性に関するinputフィールドを作ってくれるようになるので、これは超便利です。

urlオプションはフォームの送信先を定義します。create_user_pathroutes.rbusers#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_fieldinput 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">

nameidも勝手に付けてくれているのがいいですよね。
ここでid="user_name"を付与してくれているので、labelfor="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アクションをコーディングしていきます。

app/controllers/users_controller.rb
  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)

まず、@userUser.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モデルのnameemailpassword以外のデータは無視することを定義しています。

また、この関数はprivateより下に書かれています。これはクラス内からのみアクセスできる関数であることを定義しています。

さて、ここまでで@useruser_paramsで抽出されたデータが初期値として設定されたUserモデルオブジェクトが代入される、ということになります。

if @user.save
  redirect_to @user
else
  render :new
end

次は、この@usersaveして条件分岐しています。ModelのCRUDの時にも話がでてきましたがsaveメソッドはバリデーションを通りデータをDBに保存できた場合trueを、バリデーションに引っかかった場合falseを返却します。
その結果を元にtrueの場合はredirect_to @userfalseの場合はrender :newが実行されます。

redirect_to @user

redirect_toメソッドは引数にGETメソッドでリダイレクトします。
引数には@userを指定してます。これは、user_path(@user)と同義です。user_pathshowメソッドにつけられている名前です。@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が表示されるようにしてみましょう。

app/views/users/new.html.erb
  <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モデルではnameemailpassword全てが入力必須(presence)な項目です。
何も入力していなければエラーになるはず。
image.png
実際に何も入力せずに「Sign up!」ボタンを選択したページがこちらです。
「お名前」「メールアドレス」「パスワード」について、それぞれエラーが出ていてUserの作成がうまくいかなかったことがわかりますね。

文字数チェック

nameemailにはそれぞれ最大50文字、255文字の制限を設けていました。
それ以上の文字数でエラーになるか確認してみましょう。

51文字と256文字の文字列は↓をお使いください。

Name
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

Email
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb@sample.com

image.png
文字数制限のエラーが出ていますね。
ちなみに「パスワード」には適当にパスワードを入力して「Sign up!」ボタンを選択したので「パスワード」に関するエラーは出ていないです。「パスワード」はtype="password"のフィールドを使っているので、エラー時に元の値が反映されないようになっているんですね。

フォーマットチェック

emailにはフォーマットの検証もいれていました。例えば「@」がない場合はメールアドレスとしておかしいのでちゃんとエラーが返却されるか確認してみましょう。
image.png
ちゃんとエラーになっていますね。

重複チェック

最後にemailの重複チェックもみてみましょう。

とりあえずjohn@sample.comemailをもつユーザーを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]>

ユーザーを作ったので、同じメールアドレスを大文字とかにしてもエラーになるかを確認してみましょう。

image.png
これもエラーになりましたね!

ここまでチェックすれば、バリデーションはちゃんと効いていて、バリデーションエラーが起きた時のエラーハンドリングも正常に動作していることが確認できましたね。

動作確認(正常編)

ではいよいよユーザーを実際にUIから作ってみましょう。

今回は以下のユーザーを作ってみます。

name: Taro Tanaka
email: taro@sample.com
password: taro1234

image.png
ユーザー詳細ページに遷移しましたね!さらに今入力したユーザー情報もちゃんと表示されています!

Welcomeメッセージを表示する

ユーザーが作成されて、ユーザー詳細ページにも遷移できたのですが何か物足りないですね。
そうだ、Welcomeメッセージがないんだ。

ユーザー詳細ページは、Welcomeページというわけではないので今のまま装飾していけばいいのですが、会員登録した時に限ってでも「ようこそ!」みたいなメッセージがほしいですよね。

こういう一時的にページにメッセージを表示したいときに使えるRailsの機能としてflashがあります。
flashはControllerで設定してあげます。今回はcreateアクションでsaveに成功した時に表示されるようにしてみましょう。
createアクションを通ってshow.html.erbが表示された場合はWelcomeメッセージが表示されますが、通常show.html.erbが表示される場合はcreateアクションは通らずshowアクションだけを通るので、例えばリロードすればメッセージが消えるという寸法です。

app/controllers/users_controller.rb
  ...
  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も更新しましょう。

app/views/users/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_typesuccessが、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

image.png
Welcomeメッセージが表示されました!

この状態でリロードしてみてください。
image.png
メッセージが消えましたね。期待通りの動作です。

パスワードの表示非表示を制御する

あとそうだ。先ほどUX的にpassword_confirmationは使いませんという話をしました。
しかし、今のままではパスワードが非表示しか対応していないので、ユーザーは自分の思ったパスワードが正しく入力できているか確認できません。
ただ、周りから見えないようにするのが目的でマスク化しているので、常に平文にすることもUX的によろしくないでしょう。

ということで、「パスワードを表示する」チェックボックスを用意して、チェックが入っている間だけ表示されるようにしようと思います。
まず、new.html.erbにチェックボックスを追加します。
今回は@userに紐づかないフォーム要素になるのでcheck_box_tagを利用します。これはinput type="check_box"タグを作ってくれるやつです。

app/views/users/new.html.erb
  ...
  <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>
...

はい。これでチェックボックスを追加することができました。
image.png

ただ今のままではただのチェックボックスにチェックを入れたり外したりできるだけです。
このチェックボックスの状態に合わせて「パスワード」のフィールドをマスク化したりマスク解除したりしていきましょう。
どうやるかというと、今マスク化されているのはinputtypepasswordになっているからです。他のinputのフィールドは普通に文字が見えていますが、これはtypetextになっているからです。
なので、チェックボックスの状態に合わせて、チェックが入っている場合はtype="text"、チェックが入っていない場合はtype="password"と切り替えることができれば、パスワードの表示非表示を制御できるはずです。

これを実装するには、フロントエンドで動作するjavascript(jQuery)を使います。

ごちゃごちゃするといけないので、application.jsではなくファイルを追加してそちらでコーディングしていきましょう。

> quit
# touch app/javascript/packs/visible_password.js
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と書きました。これはidvisible_passwordinputタグに変化が起きたときに処理されることを意味しています。こういった何かが起こったときに処理が実行されることを『トリガー』とか『発火する』とか言うので覚えておきましょう!
今回の場合はidvisible_passwordinputの変化をトリガーにする、とか、変化が起きた時に発火する、みたいな表現をするってことです。

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")、つまりiduser_passwordの要素(パスワードのinputタグ)にattr("type", type)をしています。
attrはその要素の属性を取得したり更新したりするメソッドです。引数が2つの場合は1つ目の引数の属性を2つ目の引数の値に更新します。今回の場合はid="user_password"typeを変数typeに更新しています。

変数typeはデフォルトではpassword、チェックボックスにチェックが入っている場合はtextになるので、チェックボックスにチェックを入れるとパスワードが表示される仕組みです。

さて、実際に使えるようにするには、このファイルを読み込めるようにする必要があります。
このファイルはアプリケーションの全てのページで使うのではなく、Sign upページでのみ利用するようなファイルなので、new.html.erbで読み込みを定義してあげます。

app/views/users/new.html.erb
  <div class="container">
  ...
  </div>
+ <%= javascript_pack_tag 'visible_password' %>

Sign upページをリロードして試してみましょう!

image.png

チェックなし👆👇チェックあり

image.png

期待通りの動作になりましたね!

トップページからリンクさせる

最後にトップページの「Sign up now!」ボタンからSign upページにリンクを貼ってあげましょう。

app/views/static_pages/home.html.erb
  <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

Other Hands-on Links

1
1
0

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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?