0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Next.js×Ruby on Rails連携】管理者画面を作成する方法

Posted at

サンプル

管理者画面からPostgreSQLへ登録する方法を備忘録として記録しておきます。
image.png

画面(Next.js)の実装

登録する際に下記のエラーが出たので覚えとして対象方法を記載します。

「ActionController::ParameterMissing (param is missing or the value is empty: adminuser
Did you mean?  adminUserName):

app/controllers/adminusers_controller.rb:49:in adminuser_params'
app/controllers/adminusers_controller.rb:18:in create'
Started POST "/adminusers/create" for ::1 at 2025-03-30 19:55:15 +0900

ActionController::RoutingError (No route matches [POST] "/adminusers/create"):

Started POST "/adminUsers" for ::1 at 2025-03-30 19:58:04 +0900

ActionController::RoutingError (No route matches [POST] "/adminUsers"):

Started POST "/adminusers" for ::1 at 2025-03-30 20:00:39 +0900
Processing by AdminusersController#create as HTML
  Parameters: {"adminUserName"=>"Anderson", "adminUserEmail"=>"anderson@example.com", "adminUserPhone"=>"00111222", "adminUserPassword"=>"[FILTERED]", "adminUserCompany"=>"ABC company", "adminUserDepartment"=>"ABC Depart"}
Completed 400 Bad Request in 1ms (ActiveRecord: 0.0ms | Allocations: 302)



ActionController::ParameterMissing (param is missing or the value is empty: adminuser
Did you mean?  adminUserName):

app/controllers/adminusers_controller.rb:49:in adminuser_params'
app/controllers/adminusers_controller.rb:18:in create'」

具体的には、エラーメッセージに「param is missing or the value is empty: adminuser」と書かれており、params.require(:adminuser) が必要なパラメータを見つけられないという状況です。

Railsでは、params に渡すデータの名前が一致している必要がありますが、Next.js側の FormData では、adminUserName などのキーを渡しているため、Rails側での adminuser_params が適切に動作しません。Rails側では、params.require(:adminuser) を使って adminuser というキーを期待しているため、リクエストが一致しません。

解決策
Next.jsから送るパラメータ名を修正する: Rails側で adminuser_params が :adminuser を期待しているので、Next.js側でもその形式に合わせる必要があります。具体的には、FormData ではなく、JSON形式でデータを送信し、キー名を adminuser にラップする方法です。

Next.js側の変更: 現在、Next.jsで送信しているデータは、FormData として送信していますが、RailsはJSONを期待しているので、JSON形式でデータを送るように変更します。

FormをPost送信する際の注意点

今回のコードの場合、onSubmitの引数は、handleSubmit関数の中に引数を入れましょう。
そうでないと、サーバ側にデータがPOST送信されません。

page.tsx
 <form onSubmit={handleSubmit(onSubmit)}>
 </form>
frontend/app/adminUsers/registration/page.tsx
'use client'
import { useState,useEffect } from "react"
import { useRouter } from "next/navigation"
import axios from "axios"
import { useForm } from "react-hook-form"


export default function AdminUserRegistration(){
    const router = useRouter();
    const defaultValues = {
        adminUserName:'',
        adminUserEmail:'',
        adminUserPhone:'',
        adminUserPassword:'',
        adminUserCompany:'',
        adminUserDepartment:''
    };

    const {register,handleSubmit,formState:{errors}} = useForm({
        defaultValues
    });
    const [adminUserName,setAdminUserName] = useState('');
    const [adminUserEmail,setAdminUserEmail] = useState('');
    const [adminUserPhone,setAdminUserPhone] = useState('');
    const [adminUserPassword,setAdminUserPassword] = useState('');
    const [adminUserCompany,setAdminUserCompany] = useState('');
    const [adminUserDepartment,setAdminUserDepartment] = useState('');

    const onSubmit = async (data: any) => {
        const formData = new FormData();
        formData.append('adminUserName',adminUserName);
        formData.append('adminUserEmail',adminUserEmail);
        formData.append('adminUserPhone',adminUserPhone);
        formData.append('adminUserPassword',adminUserPassword);
        formData.append('adminUserCompany',adminUserCompany);
        formData.append('adminUserDepartment',adminUserDepartment);
        try {
            const response = await axios.post('http://localhost:3000/adminusers', {
                adminuser: {  // adminuserというラッパーを使う
                    adminUserName: data.adminUserName,
                    adminUserEmail: data.adminUserEmail,
                    adminUserPhone: data.adminUserPhone,
                    adminUserPassword: data.adminUserPassword,
                    adminUserCompany: data.adminUserCompany,
                    adminUserDepartment: data.adminUserDepartment
                }
            }, {
                headers: {
                    'Content-Type': 'application/json'  // 明示的にJSON形式で送信
                }
            });

            if (response.status === 200) {
                alert('Admin User Registered successfully');
                console.log(response.data);
            } else {
                console.log(response.data);
            }
        } catch (error) {
            console.error(error);
            alert('Error occurred while registering the admin user');
        }
    };

    return (
        <form onSubmit={handleSubmit(onSubmit)}>
            <div>
                <label>Name</label>
                <input
                    type="text"
                    className="w-full border border-gray-500 rounded-md"
                    defaultValue={defaultValues.adminUserName}
                    {...register('adminUserName',{
                        required:'AdminUserNamwe must be required.'
                    })}
                    onChange={(e)=>setAdminUserName(e.target.value)}
                />
                <div className="text-rose-500">{errors.adminUserName?.message}</div>
            </div>
            <div>
                <label>Email</label>
                <input
                    type="email"
                    className="w-full border border-gray-500 rounded-md"
                    defaultValue={defaultValues.adminUserEmail}
                    {...register('adminUserEmail',{
                        required:'AdminuserEmail must be required.'
                    })}
                    onChange={(e)=>setAdminUserEmail(e.target.value)}
                />
                <div className="text-rose-500">{errors.adminUserEmail?.message}</div>
            </div>
            <div>
                <label>Phone</label>
                <input
                    type="text"
                    className="w-full border border-gray-500 rounded-md"
                    defaultValue={defaultValues.adminUserPhone}
                    {...register('adminUserPhone',{
                        required:'AdminUserPhone must be required.'
                    })}
                    onChange={(e)=>{setAdminUserPhone(e.target.value)}}
                />
                <div className="text-rose-500">{errors.adminUserPhone?.message}</div>
            </div>
            <div>
                <label>Password</label>
                <input
                    type="password"
                    className="w-full border border-gray-500 rounded-md"
                    defaultValue={defaultValues.adminUserPassword}
                    {...register('adminUserPassword',{
                        required:'AdminUserPassword must be required.'
                    })}
                    onChange={(e)=>setAdminUserPassword(e.target.value)}
                />
                <div className="text-rose-500">{errors.adminUserPassword ?.message}</div>
            </div>
            <label>Company</label>
            <input
                type="text"
                className="w-full border border-gray-500 rounded-md"
                defaultValue={defaultValues.adminUserCompany}
                {...register('adminUserCompany',{
                    required:'Company must be required.'
                })}
                onChange={(e)=>setAdminUserCompany(e.target.value)}
            />
            <div className="text-rose-500">{errors.adminUserCompany?.message}</div>
            <div>
                <label>Department</label>
                <input
                    type="text"
                    className="w-full border border-gray-500 rounded-md"
                    defaultValue={defaultValues.adminUserDepartment}
                    {...register('adminUserDepartment',{
                        required:'Departmanet muset be required.'
                    })}
                    onChange={(e)=>{setAdminUserDepartment(e.target.value)}}
                />
                <div className="text-rose-500">{errors.adminUserDepartment?.message}</div>
            </div>
            <div>
                <button
                    type="submit"
                    className="bg bg-blue-500 text-white rounded-md px-4 py-4"
                >
                    Register
                </button>
                <button
                    type="button"
                    className="bg bg-green-500 text-white rounded-md px-4 py-4"
                >
                    Back to Top
                </button>
            </div>
        </form>
    )
}

サーバ側(Ruby on Rails)の処理

bcrypt Gemのインストール

まず、bcrypt ジェムをインストールします。これを使用すると、パスワードを安全にハッシュ化できます。

Gemfileに以下を追加します。

gem 'bcrypt', '~> 3.1.7'

そして、次のコマンドでインストールします。

bundle install
backend/controllers/adminusers_controller.rb
class AdminusersController < ApplicationController
  before_action :set_adminuser, only: %i[ show update destroy ]

  # GET /adminusers
  def index
    @adminusers = Adminuser.all

    render json: @adminusers
  end

  # GET /adminusers/1
  def show
    render json: @adminuser
  end

  # POST /adminusers
  def create
    @adminuser = Adminuser.new(adminuser_params)

    #Generate hash password
    @adminuser.adminUserPassword = BCrypt::Password.create(@adminuser.adminUserPassword)

    if @adminuser.save
      render json: @adminuser, status: :created, location: @adminuser
    else
      render json: @adminuser.errors, status: :unprocessable_entity
    end
  end

  # PATCH/PUT /adminusers/1
  def update
    if @adminuser.update(adminuser_params)
      render json: @adminuser
    else
      render json: @adminuser.errors, status: :unprocessable_entity
    end
  end

  # DELETE /adminusers/1
  def destroy
    @adminuser.destroy!
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_adminuser
      @adminuser = Adminuser.find(params[:id])
    end

    # Only allow a list of trusted parameters through.
    def adminuser_params
      params.require(:adminuser).permit(:adminUserName, :adminUserEmail, :adminUserPhone, :adminUserPassword, :adminUserCompany, :adminUserDepartment)
    end
end

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?