見出し画像

User登録の問題を解決

ユーザ情報の登録にはデータベースの保存も重要だが、ユーザに入力してもらう情報なので、セキュリティと入力制限は必要である。そのため、ある程度の規則をもとに入力してもらうことが必要である。

nameとemailが空白でも登録できてしまう。

ユーザーに必ず入力してもらいたい項目があるなら必須入力にしなくてはならないため、バリデーションという手法を用いる
・バリデーション
フォームに入力されたデータが有効なものかどうかをチェックすることをバリデーションと言う
Railsにはデータ保存前に、バリデーションを自動的に行うようにするvalidatesメソッドが用意されている
空白(未入力)かどうか判定する「presence」を使う
Userモデルに、以下のような追記をする
app/models/user.rb
class User < ApplicationRecord
validates :name, presence: true
validates :email, presence: true
end

代表的なオプションは以下の通りです。
・presence空でないかどうか
・uniqueness重複していないかどうか
・length長さを指定する(例:文字の長さ)
・numericality数値のみ受け付ける
validatesを組み合わせることでデータの整合性を保つことができ、思わぬバグも発生しづらくなる

登録後のフィードバックが表示されないため登録できたのかわからない

一般的なWebサービスでは、ユーザーが意図した処理を行えたかどうかを認識させる
app/controllers/users_controller.rb
def create
@user = User.new(name: params[:user][:name], email: params[:user][:email])
if @user.save
redirect_to root_path, success: '登録が完了しました'
else
flash.now[:danger] = "登録に失敗しました"
render :new
end
end
app/assets/stylesheets/custom.scss
.alert {
margin-bottom: 0px;
position: fixed;
width: 100%;
z-index: 10000;
}
app/views/layouts/application.html.erb
<% flash.each do |key, value| %>
<div class="alert alert-<%= key %>" role="alert"><%= value %></div>
<% end %>
<%= yield %>
app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
add_flash_types :success, :info, :warning, :danger
end
renderやredirectで指定された「notice」や「alert」はRailsが自動的に用意するflashという変数に保存される
flashは
flash: {
alert: "登録に失敗しました"
}
上のようにhashという形式で定義されており、Viewのerbファイルで<%= flash[:alert] %>のように記述することで、表示可能

jQueryの導入

javascriptのフレームワークにjQueryというものがあります。簡単に言うと、javascriptを簡単に使えるようにしたものがjQuery
jQueryのgemを導入する
Gemfile
gem "jquery-rails"
gemを追記したら、bundle install
次に、jQueryを使えるように宣言するため、下記を追記
app/assets/javascripts/application.js
//= require jquery
Rails serverの再起動を忘れずに
app/views/layouts/application.html.erb
<% flash.each do |key, value| %>
<div class="alert alert-<%= key %>" role="alert"><%= value %></div>
<% end %>
<%= yield %>
<script>
$(function(){
$(".alert").fadeOut(5000);
});
</script>

アラートが表示されたら5秒かけてフェードアウトするコード
paramsのセキュリティ
「ストロングパラメーター」という機能を使い、不要な情報を受け取らないように設定
app/controllers/users_controller.rb
class UsersController < ApplicationController
def new
@user = User.new
end
def create
@user = User.new(user_params)
if @user.save
redirect_to root_path, success: "登録に成功しました"
else
flash.now[:danger] = "登録に失敗しました"
render :new
end
private #クラス内部でしか利用できないようにする
def user_params
params.require(:user).permit(:name, :email) #userをrequireで呼び出し 、nameとemailのパラメータのみを許可
end

end
end
privateを使ったメソッドは、classの外部からは呼び出せない
そのclass内でしか実行されないメソッドを作成するのに使う

パスワード機能の追加

has_secure_password
パスワードの実装には「has_secure_password」というメソッドを使用する
パスワードを実装したいモデルに、以下のコードを追加
app/models/user.rb
class User < ApplicationRecord
validates :name, presence: true
validates :email, presence: true
has_secure_password
end
has_secure_passwordを使うことで、以下のような機能を簡単に実装可能
・暗号化されたパスワードをデータベースのpassword_digestというカラムに保存できるようになる。
・passwordとpassword_confirmationが使えるようになる。また、存在性と値が一致するかどうかのバリデーション(チェック)も追加される。
・引数の文字列がパスワードと一致するとUserオブジェクトを返し、間違っているとfalseを返す
・authenticateメソッドが使えるようになる。
password_digest
has_secure_passwordを使うにはhas_secure_passwordを持つモデルにpassword_digestカラムが必要になる
rails gコマンドでmigrationファイルを生成する
$ rails g migration add_password_digest_to_users password_digest:string
コマンドで次のようなmigrationファイルが生成される
class AddPasswordDigestToUsers < ActiveRecord::Migration[5.1]
def change
add_column :users, :password_digest, :string
end
end

add_columnメソッドを使って、userテーブルにpassword_digestカラムを追加
$ rails db:migrate
を実行し、このmigrationファイルを読み込む

bcrypt

has_secure_passwordは内部で暗号化する際にbcryptと言うgemを使用している
bcryptのgemのインストールをする
Gemfile
gem 'bcrypt'
$ bundle install
app/controllers/users_controller.rb
private
def user_params
params.require(:user).permit(:name, :email, :password, :password_confirmation)
end

以下のようにフォームが変更されれば成功

入力制限を行い、エラーを返したりすることでユーザにわかるように行った。また、すトロングパラメータを利用することでクラス外でparamsを利用できなくすることで、改ざんが行われないようにした。今回の方法は基本的なところであるため、しっかり身につけたいと思う。とくにバリデーションは奥が深いところまで色々あるため、自分でWebを作るときはうまく使えるといいと思う。

この記事が気に入ったらサポートをしてみませんか?