1
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Rails】Rails APIで新規登録、退会処理

Posted at

前回、Rails APIでUser周りの実装をしました。
【Rails】JWTを用いたUser周りのAPI実装
その記事の新規登録、退会処理で気になったことをまとめます。
先にmodel、controllerを貼り付けておきます。

models/usr.rb
class User < ApplicationRecord
  before_save { self.email = email.downcase }
  validates :name, presence: true, length: { maximum: 50 }
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  validates :email, presence: true, length: { maximum: 255 },
                    format: { with: VALID_EMAIL_REGEX },
                    uniqueness: true
  has_secure_password
  validates :password, presence: true, length: { minimum: 6 }
end
controllers/api/v1/users_controller.rb
module Api
  module V1
    class UsersController < ApiController
      # ユーザー登録
      def create
        user = User.new(user_params)
        if user.save
          render json: { message: "ユーザー登録が完了しました", user: {id: user.id, name: user.name, email: user.email} }, status: :created
        else
          render json: { errors: user.errors.full_messages }, status: :unprocessable_entity
        end
      end

      # プロフィール削除(退会処理)
      def destroy
        user = current_user
        if user && user.destroy
          render json: { message: "アカウントが削除されました。" }, status: :ok
        else
          render json: { error: "アカウントの削除に失敗しました" }, status: :unprocessable_entity
        end
      end

      private

      # ユーザー登録時のパラメータ
      def user_params
        params.require(:user).permit(:name, :email, :password, :password_confirmation)
      end
      wrap_parameters :user, include: [:name, :email, :password, :password_confirmation]
    end
  end
end

has_secure_password

RailsのActiveRecordモデルで、ユーザーのパスワードを安全に管理するためのメソッドです。このメソッドを使用すると、パスワードのハッシュ化、パスワード確認、認証機能などが自動的に提供され、セキュリティ強化が簡単に行えます。

has_secure_passwordの前提条件

  • bcrypt Gemが必要
    bcryptというGemが必要です。このGemは、パスワードのハッシュ化と比較を行うために使用されます。Gemfileに以下を追加し、bundle installでインストールします。
gem 'bcrypt', '~> 3.1.7'
  • password_digestカラムが必要
    モデルのデータベーステーブルにpassword_digestという名前のカラムを必要とします。このカラムにハッシュ化されたパスワードが保存されます。

主な機能と動作

has_secure_passwordをモデルに追加するだけで、次の機能が自動的に利用できるようになります。

  • パスワードのハッシュ化
    • ユーザーがパスワードを設定(password)すると、bcryptによってハッシュ化され、password_digestカラムに保存されます
    • ハッシュ化されるため、実際のパスワード文字列はデータベースに保存されません。データベースに保存されるのはハッシュ化された文字列のみです
  • passwordとpassword_confirmation属性
    • passwordとpassword_confirmationという仮想属性がモデルに追加されます
    • ユーザーが新しいパスワードを設定するときに、password_confirmationに同じパスワードを入力することで、パスワードの一致を確認できます
    • passwordとpassword_confirmationが一致しない場合、バリデーションエラーが発生します
  • 認証機能
    • authenticateメソッドが自動的に提供されます。このメソッドにパスワードを渡して、ユーザーの認証を行います
    • authenticateは、渡されたパスワードをハッシュ化し、password_digestと比較します。一致すればユーザーオブジェクトを返し、不一致ならfalseを返します。
user = User.find_by(email: params[:email])
if user&.authenticate(params[:password])
  # 認証成功
else
  # 認証失敗
end

user_params

RailsのStrong Parametersという仕組みを使って、ユーザーからのリクエストパラメータを安全にフィルタリングするためのメソッドです。
ユーザーが送信するデータ(params)のうち、許可された属性のみを受け取り、他の属性を除外することで、不正なデータがモデルに渡されないようにします。

params.require(:user)

paramsは、コントローラが受け取るリクエストのデータが含まれるオブジェクトです。たとえば、フォーム送信やAPIリクエストから送られた情報はすべてparamsで受け取ります。

  • require(:user)は、paramsオブジェクトから:userというキーを必須項目として要求します。この例では、リクエストデータがuserというキーの下に存在することが前提になっています
  • require(:user)がない場合、:userキーが存在しないときにエラーを発生させることができず、モデルに想定外のデータが渡ってしまう可能性があります

permit(:name, :email, :password, :password_confirmation)

permitは、paramsの中で許可したいキー(属性)を指定します。この例では、:name、:email、:password、:password_confirmationのみを許可しています。

  • 許可された属性のみが最終的にuser_paramsメソッドから返され、User.newメソッドに渡されます
  • 許可されていない属性は自動的に削除されるため、予期しないパラメータの混入や、悪意のあるデータの挿入を防ぐことができます

wrap_parameters

Railsのコントローラにおいてリクエストパラメータのラップ(ラッピング)を行うためのメソッドです。これにより、JSONリクエストのデータが適切な形で扱いやすくなります。

背景と目的

JSON形式でデータを送信するとき、リクエストボディが特定のキーにラップされていることを期待することがあります。wrap_parametersを使うことで、外部APIやクライアントから受け取るデータの形式に柔軟に対応できます。
クライアントから次のようなJSONデータが送信されるとします:

json
{
  "name": "John Doe",
  "email": "john@example.com",
  "password": "secret123"
}

Railsのparamsはデフォルトでデータがモデル名にラップされることを期待するため、次のようにラップされていることが理想です:

json
{
  "user": {
    "name": "John Doe",
    "email": "john@example.com",
    "password": "secret123"
  }
}

wrap_parametersを使用すると、クライアントがこのラップされた形式で送信しなくても、Rails側で自動的にラップして処理できるようになります。

使用方法

wrap_parametersは、コントローラ内部やアプリケーション全体の設定で利用できます。コントローラ内で使用する場合は以下のように書きます:

ruby
class Api::V1::UsersController < ApplicationController
  wrap_parameters :user, include: [:name, :email, :password, :password_confirmation]
end
  • wrap_parameters :user
    :userの部分は、どのキーでラップするかを指定します。この場合、ラップ後のデータがparams[:user]として扱えるようになります。
  • include: [:name, :email, :password, :password_confirmation]
    includeオプションで、ラップする際に含める属性を指定します。ここで指定した属性が含まれるJSONデータのみがラップされ、params[:user][:name]といったアクセスが可能になります。
1
4
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
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?