戻る

Rails6.0


民泊サイトの構築 Rails6.0

  (0)
3,000円

タスク2-4   氏名認証

このタスクについて


タスクの内容を一部抜粋します。
プロジェクトを購入していただくとこのタスクの内容の全てを読みやすい表示で見ることができます。
プログラムコードが色分けされて見やすくなります。
プログラムコードに行番号が付きます。
本文が色分けされて見やすくなります。
そしてこのアプリケーションのフルコードをダウンロードすることが可能になります。




ユーザーモデルに氏名の項目を追加します。


コマンド
rails g migration AddFullnameToUser full_name:string


コマンド マイグレーション適用
rails db:migrate


HeidiSQLでテーブル確認



full_nameフィールドの確認




ユーザモデルにバリデーションを追加します。


記述追加 app\models\user.rb(7行目)
validates :full_name, presence: true, length: {maximum: 50}



app\models\user.rb
class User < ApplicationRecord

  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable

  validates :full_name, presence: true, length: {maximum: 50}
end



ストロングパラメータを追加します。
「app\controllers\application_controller.rb」ファイルを以下のように更新して下さい。


記述更新 app\controllers\application_controller.rb
class ApplicationController < ActionController::Base

    before_action :configure_permitted_parameters, if: :devise_controller?

    protected
    def configure_permitted_parameters
        devise_parameter_sanitizer.permit(:sign_up, keys: [:full_name])
        devise_parameter_sanitizer.permit(:account_update, keys: [:full_name])
    end
    
end



認証ビューを更新します。


記述更新 app\views\devise\registrations\new.html.erb
<section class="hero is-dark is-fullheight">
  <div class="hero-body">
    <div class="container">
      <div class="columns is-centered">
        <div class="column is-6-table is-6-desktop is-6-widescreen">
          <div class="box">
            
            <div class="field has-text-centered">
              <strong>新規ユーザ登録</strong>
            </div>
            <%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
              <%= render "devise/shared/error_messages", resource: resource %>
              <div class="field">
                <%= f.label :氏名, class: "label" %>
                <%= f.text_field :full_name, autofocus: true, autocomplete: "full_name", class: "input" %>
              </div>
              <div class="field">
                <%= f.label :メールアドレス, class: "label" %>
                <%= f.email_field :email, autofocus: true, autocomplete: "email", class: "input" %>
              </div>
              <div class="field">
                <%= f.label :パスワード, class: "label" %>
                <% if @minimum_password_length %>
                <em>(<%= @minimum_password_length %> 文字以上)</em>
                <% end %><br />
                <%= f.password_field :password, autocomplete: "new-password", class: "input" %>
              </div>
              <div class="field">
                <%= f.label :確認, class: "label" %>
                <%= f.password_field :password_confirmation, autocomplete: "new-password", class: "input" %>
              </div>
              <div class="field">
                <%= f.submit "登録する", class: "button is-danger is-fullwidth m-t-10 m-b-10" %>
              </div>
            <% end %>
            <%= render "devise/shared/links" %>
          </div>
        </div>
      </div>
    </div>
  </div>
</section>



ブラウザ確認
http://localhost:3000/users/sign_up



新規ユーザ登録




セッションビューの編集をします。


記述更新 app\views\devise\sessions\new.html.erb
<section class="hero is-dark is-fullheight">
  <div class="hero-body">
    <div class="container">
      <div class="columns is-centered">
        <div class="column is-6-table is-6-desktop is-6-widescreen">
          <div class="box">
            
            <div class="field has-text-centered">
              <strong>ログイン</strong>
            </div>
            <%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
              <div class="field">
                <%= f.label :メールアドレス, class: "label" %>
                <%= f.email_field :email, autofocus: true, autocomplete: "email", class: "input" %>
              </div>
              <div class="field">
                <%= f.label :パスワード, class: "label" %>
                <%= f.password_field :password, autocomplete: "current-password", class: "input" %>
              </div>
              <% if devise_mapping.rememberable? %>
                <div class="field">
                  <%= f.check_box :remember_me %>
                  <%= f.label :ログインを保持する %>
                </div>
              <% end %>
              <div class="field">
                <%= f.submit "ログインする", class: "button is-danger is-fullwidth m-t-10 m-b-10" %>
              </div>
            <% end %>
            <%= render "devise/shared/links" %>
          </div>
        </div>
      </div>
    </div>
  </div>
</section>



ブラウザ確認
http://localhost:3000/users/sign_in



ログイン




アカウント編集ページを更新します。


記述更新 app\views\devise\registrations\edit.html.erb
<section class="hero is-dark is-fullheight">
  <div class="hero-body">
    <div class="container">
      <div class="columns is-centered">
        <div class="column is-6-table is-6-desktop is-6-widescreen">
          <div class="box">
            
            <div class="field has-text-centered">
              <strong>ユーザ登録情報編集</strong>
            </div>
            <%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %>
              <%= render "devise/shared/error_messages", resource: resource %>
              <div class="field">
                <%= f.label :氏名, class: "label" %>
                <%= f.text_field :full_name, autofocus: true, autocomplete: "full_name", class: "input" %>
              </div>
              <div class="field">
                <%= f.label :メールアドレス, class: "label" %>
                <%= f.email_field :email, autofocus: true, autocomplete: "email", class: "input" %>
              </div>
              <% if devise_mapping.confirmable? && resource.pending_reconfirmation? %>
                <div>現在、確認を待っています: <%= resource.unconfirmed_email %></div>
              <% end %>
              <div class="field">
                <%= f.label :パスワード, class: "label"  %> <i>(変更しない場合は空白のままにします)</i>
                <%= f.password_field :password, autocomplete: "new-password", class: "input" %>
                <% if @minimum_password_length %>
                  <br />
                  <em><%= @minimum_password_length %> 文字以上</em>
                <% end %>
              </div>
              <div class="field">
                <%= f.label :確認, class: "label"  %>
                <%= f.password_field :password_confirmation, autocomplete: "new-password", class: "input" %>
              </div>
              <div class="field">
                <%= f.label :現在のパスワード, class: "label"  %> <i>(変更するには現在のパスワードが必要です)</i><br />
                <%= f.password_field :current_password, autocomplete: "current-password", class: "input" %>
              </div>
              <div class="field">
                <%= f.submit "更新する", class: "button is-danger is-fullwidth" %>
              </div>
            <% end %>
            <%= link_to "戻る", :back, class: "button is-fullwidth m-t-10" %>
          </div>
        </div>
      </div>
    </div>
  </div>
</section>



ブラウザ確認
ログインしておく必要があります。
http://localhost:3000/users/edit



氏名カラムが更新できる




スタイルを更新します。


「app\assets\stylesheets」フォルダに「styles.scss」ファイルを新規作成してください。


app\assets\stylesheets\styles.scss(新規作成したファイル)
これからのものもすべて書いておきます。
$spaceamounts: (0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 60, 70, 80, 90, 100);
$sides: (top, bottom, left, right);
@each $space in $spaceamounts {
    @each $side in $sides {
        .m-#{str-slice($side, 0, 1)}-#{$space} {
            margin-#{$side}: #{$space}px !important;
        }
        .p-#{str-slice($side, 0, 1)}-#{$space} {
            padding-#{$side}: #{$space}px !important;
        }
    }
    .m-#{$space} {
        margin: #{$space}px !important;
    }
    .p-#{$space} {
        padding: #{$space}px !important;
    }
    .h-#{$space} {
        margin-top: #{$space}px !important;
        margin-bottom: #{$space}px !important;
    }
    .f-#{$space} {
        font-size: #{$space}px !important;
    }
}
.is-horizontal-center {
  justify-content: center;
}
.small-title {
  font-size: 10px;
}
.star-review {
  color: #ffbf00;
  font-size: 13px;
  font-weight: 600;
}
// ドロップゾーン用
.dropzone {
  border: 2px dashed #0087F7 !important;
  border-radius: 5px;
  background: white;
}
.dropzone .dz-message {
  font-weight: 400;
}
.dropzone .dz-message .note {
  font-size: 0.8em;
  font-weight: 200;
  display: block;
  margin-top: 1.4rem;
}
//フォーム
.form-container {
  margin-left: 100px;
  margin-right: 100px;
}
//ページネーション
.pagination-link.is-current {
  background-color: #ee7979 !important;
  border-color: #ee7979 !important;
}
//ホームページ用
.has-bg-img {
  background: url('/assets/home/background01.jpg') center center;
  background-size: cover;
}
//アバター オンライン
.avatar {
  position: relative;
  display: inline-block;
  &::before {
    content: '';
    position: absolute;
    top: -2px;
    right: -2px;
    width: 10px;
    height: 10px;
    border-radius: 100%;
    border: 1px solid white;
  }
  &.online:before {
    background-color: #1dbf73;
  }
  &.offline:before {
    background-color: gray;
  }
}
//ナビバーのアバター画像位置
.image {
  //margin-top: 0.6rem;
  display: flex; /* flexに */
  align-items: center;
}
//メッセージ
.conversation-message {
  margin-bottom: 5px !important;
  padding: 10px !important;
  font-size: 15px;
}
//カレンダー
.fc-past {
  background-color: lightgray;
}
.fc-event {
  border: none !important;
  background-color: transparent;
}
.fc-title {
  font-size: 14px;
  font-weight: 500;
  position: relative;
  top: 8px;
  left: 20px;
}
.fc-content.Waiting {
    background-color: #C9CC6D;
  }
  
.fc-content {
    background-color: #00A699;
    height: 40px;
    border-radius: 20px;
}
.fc-day {
    position: relative;
}
.day-price {
    position: absolute;
    color: #EAA90B;
    bottom: 2px;
    right: 2px;
}
.badge {
    background-color: #FF5A5F;
    position: relative;
    top: -15px;
    left: -5px;
}
#add-card form {
    width: 480px;
    margin: 20px auto;
}
#add-card label {
    position: relative;
    color: #6A7C94;
    font-weight: 400;
    height: 48px;
    line-height: 48px;
    margin-bottom: 10px;
    display: block;
}
#add-card label > span {
    float: left;
}
#add-card button {
    float: left;
    display: block;
    background-image: linear-gradient(-180deg, #F8B563 0%, #F99A52 100%);
    box-shadow: 0 1px 2px 0 rgba(0,0,0,0.10), inset 0 -1px 0 0 #E57C45;
    color: white;
    border-radius: 24px;
    border: 0;
    margin-top: 20px;
    font-size: 17px;
    font-weight: 500;
    width: 100%;
    height: 48px;
    line-height: 48px;
    outline: none;
}
#add-card button:focus {
    background: #EF8C41;
}
#add-card button:active {
    background: #E17422;
}
.outcome {
    float: left;
    width: 100%;
    padding-top: 8px;
    min-height: 20px;
    text-align: center;
}
.success, .error {
    display: none;
    font-size: 13px;
}
.success.visible, .error.visible {
    display: inline;
}
.error {
    color: #E4584C;
}
// スライダー
.sidebar-list {
    padding-left: 0;
    list-style: none;
}
.sidebar-item {
    padding: 10px 0;
    font-size: 16px;
    color: #82888a;
}
.sidebar-link {
    color: #82888a;
    text-decoration: none;
}
.sidebar-link:hover, .sidebar-link:focus {
    color: #CACCCD;
    text-decoration: none;
}
.active.sidebar-link {
    color: #565A5C;
    font-weight: bold;
    text-decoration: none;
}
// googlフォント用
.title {
  font-family: 'Kosugi Maru', "Helvetica Neue", "Helvetica", "Arial", sans-serif;
}
.button {
  font-family: 'Kosugi Maru', "Helvetica Neue", "Helvetica", "Arial", sans-serif;
}
.field {
  font-family: 'Kosugi Maru', "Helvetica Neue", "Helvetica", "Arial", sans-serif;
}
.all {
  font-family: 'Kosugi Maru', "Helvetica Neue", "Helvetica", "Arial", sans-serif;
}
.navbar-item {
  font-family: 'Kosugi Maru', "Helvetica Neue", "Helvetica", "Arial", sans-serif;
}
.input {
  font-family: 'Kosugi Maru', "Helvetica Neue", "Helvetica", "Arial", sans-serif;
}
.card-content {
  font-family: 'Kosugi Maru', "Helvetica Neue", "Helvetica", "Arial", sans-serif;
}
.section {
  font-family: 'Kosugi Maru', "Helvetica Neue", "Helvetica", "Arial", sans-serif;
}
.card-header-title is-centered {
  font-family: 'Kosugi Maru', "Helvetica Neue", "Helvetica", "Arial", sans-serif;
}
.modal-card-title {
  font-family: 'Kosugi Maru', "Helvetica Neue", "Helvetica", "Arial", sans-serif;
}
// 部屋の表示
.amenities li {
    margin-bottom: 10px;
    font-size: 16px;
    list-style-type: none;
}
.amenities .text-line-through {
    text-decoration: line-through;
    color: rgba(0,0,0,0.45);
    font-size: 14px;
}
// 予約
.reservation-table td {
    width: 100%;
    border: none;
    border-bottom: 1px solid #dce0e0;
    padding: 10px;
}
.reservation-table .total td {
    font-size: 16px;
    font-weight: bold;
    border: none;
}
.form-control.datepicker {
    color: #00A699;
    background-color: white;
    border: 1px solid #00A699;
    text-align: center;
}
.message-alert {
    color: #d43242;
    font-size: 14px;
    padding-top: 10px;
}
// 検索
#main {
    height: 100%;
    overflow: hidden;
}
#left {
    padding: 10px 400px 10px 20px;
    overflow: scroll;
    height: 100%;
}
#right {
    position: fixed;
    top: 0;
    right: 0;
    width: 450px;
    height: 100%;
}
.map_price {
    text-align: center;
    font-size: 16px;
    font-weight: 600;
    color: #00A699;
}
//通知用数字
.badge {
  background-color: #fad4d4;
  position: relative;
  top: -15px;
  left: -15px;
  border-radius: 50%;
  padding-left: 5px;
  padding-right: 5px;
}
.icon-babu {
  color:#14cfe7;
}



レンダーファイルを更新します。


記述更新 app\views\devise\shared\_links.html.erb
<br/>
<div class="all">
<%- if controller_name != 'sessions' %>
  ユーザ登録がお済みの方は<%= link_to "ログイン", new_session_path(resource_name) %>してください。<br />
  <br/>
  <p>登録ボタンを押すとメールが送信されます。</p>
  <p>メールに記載されているリンクをクリックするとアカウントが有効化されます。</p>
<% end %>
<%- if devise_mapping.registerable? && controller_name != 'registrations' %>
  <%= link_to "新規ユーザ登録", new_registration_path(resource_name) %>がお済みでない方は先に登録をお願い致します。<br />
<% end %>
<%- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations' %>
  <%= link_to "パスワードをお忘れですか?", new_password_path(resource_name) %><br />
<% end %>
<%- if devise_mapping.confirmable? && controller_name != 'confirmations' %>
<br/>
  <%= link_to "確認のメールが届かない方はこちら", new_confirmation_path(resource_name) %><br />
<% end %>
<%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' %>
  <%= link_to "ロック解除の手順を受け取っていませんか?", new_unlock_path(resource_name) %><br />
<% end %>
</div>



パスワードリセットのビューを更新します。


記述更新 app\views\devise\passwords\new.html.erb
<section class="hero is-dark is-fullheight">
  <div class="hero-body">
    <div class="container">
      <div class="columns is-centered">
        <div class="column is-6-table is-6-desktop is-6-widescreen">
          <div class="box">
            <div class="field has-text-centered">
              <strong>パスワードをお忘れですか?</strong>
            </div>
            <br/>
            <%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f| %>
              <%= render "devise/shared/error_messages", resource: resource %>
              <div class="field">
                <%= f.label :メールアドレス, class: "label" %>
                <%= f.email_field :email, autofocus: true, autocomplete: "email", placeholder: "メールアドレスを入力してください", class: "input" %>
              </div>
              <br/>
              <div class="actions">
                <%= f.submit "パスワード再設定メールを送る", class: "button is-danger is-fullwidth m-t-10 m-b-10" %>
              </div>
            <% end %>
            <br/>
            <p>メールに記載されているリンクをクリックするとパスワードの再設定ができます。</p>
          </div>
        </div>
      </div>
    </div>
  </div>
</section>



ブラウザ確認
http://localhost:3000/users/password/new



パスワードをお忘れの方用




パスワード変更のビューを更新します。
メール送信設定を行なった後でなければ確認できませんが変更しておきます。


app\views\devise\passwords\edit.html.erb
<section class="hero is-dark is-fullheight">
  <div class="hero-body">
    <div class="container">
      <div class="columns is-centered">
        <div class="column is-6-table is-6-desktop is-6-widescreen">
          <div class="box">
            <div class="field has-text-centered">
              <strong>パスワードを変更します</strong>
            </div>
            <br/>
            <%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put }) do |f| %>
              <%= render "devise/shared/error_messages", resource: resource %>
              <%= f.hidden_field :reset_password_token %>
              <div class="field">
                <% if @minimum_password_length %>
                  <em>新しいパスワード(<%= @minimum_password_length %> 文字以上)</em><br />
                <% end %>
                <%= f.password_field :password, autofocus: true, autocomplete: "new-password", placeholder: "新しいパスワードを入力して下さい", class: "input" %>
              </div>
              <br/>
              <div class="field">
                <%= f.password_field :password_confirmation, autocomplete: "new-password", placeholder: "確認", class: "input" %>
              </div>
              <br/>
              <div class="actions">
                <%= f.submit "パスワードを変更する", class: "button is-danger is-fullwidth m-t-10 m-b-10" %>
              </div>
            <% end %>
          </div>
        </div>
      </div>
    </div>
  </div>
</section>



ナビゲーションバーのドロップダウンの部分を氏名表示に変更します。
確認するには氏名のカラムを更新しておく必要があります。


1.35行目の記述を以下の記述に更新しています。
<a class="navbar-item"><%= current_user.full_name %></a>



2.37行目に以下のリンクを追加しています。
<%= link_to  "ユーザ登録情報編集", edit_user_registration_path, class: "navbar-item" %>



この続きはプロジェクトを購入していただくことで見ることができます。
プロジェクトを購入していただくとこのタスクの内容の全てを読みやすい表示で見ることができます。
プログラムコードが色分けされて見やすくなります。
プログラムコードに行番号が付きます。
本文が色分けされて見やすくなります。
そしてプロジェクトを購入するとこのアプリケーションのフルコードをダウンロードすることができます。

まだレビューはありません。

民泊サイトの構築 Rails6.0

3,000円

Rails6.0で民泊サイトを構築します。
ホストは部屋を登録し、ゲストは宿泊予約できます。
ゲストはクレジットカードで支払いをし、ホストには料金の80%が自動で口座に振り込まれます。
Googleマップによる表示、AJAX検索、日付カレンダーによる予約ができます。
リアルタイムメッセージにより連絡がとれます。
予約確認メールの送信も可能。
写真のアップロード機能、アマゾンS3の利用方法も解説。
レビュー機能の実装方法解説。
フルカレンダー による予約管理。
HEROKUへのデプロイ方法を解説。
フルコードのダウンロード可能。

タスク数: 128