Ruby on Rails - モデルの検証を考案する
概要
私は Ruby on Rails アプリケーションに取り組んでおり、認証に Devise gem を使用しています。新しいユーザーとしてサインアップすることはできますが、ユーザーのすべてのデータが Devise User モデルに保存されていないことに注意しました。
以下のシナリオについて説明しました。
ActiveRecord::Schema[7.0].define(version: 2023_08_07_053734) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "company_departments", force: :cascade do |t|
t.integer "department_code"
t.string "department_name"
t.string "department_haed"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.string "user_name"
t.integer "user_identification_number"
t.date "user_employment_start_date"
t.date "user_DOB"
t.string "user_present__job_title"
t.string "user_department"
t.string "user_employment_category"
t.string "user_office_working_preference"
t.string "user_social_status"
t.string "user_present_office_location"
t.string "user_present_working_shift"
t.bigint "user_basic_pay"
t.bigint "user_gross_salary"
t.integer "user_appraisal_rating"
t.date "user_last_salary_revision_date"
t.text "user_appraisal_comments"
t.bigint "user_contact"
t.string "user_personalemail"
t.text "user_permanent_address"
t.string "user_manager"
t.string "user_sup1"
t.string "user_sup2"
t.string "user_sup3"
t.string "user_sup4"
t.text "user_permanent_illness"
t.string "user_phstatus"
t.string "user_companyname"
t.string "user_skill_category"
t.boolean "user_account_status"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.string "confirmation_token"
t.datetime "confirmed_at"
t.datetime "confirmation_sent_at"
t.string "unconfirmed_email"
t.integer "failed_attempts", default: 0, null: false
t.string "unlock_token"
t.datetime "locked_at"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.bigint "company_department_id"
t.index ["company_department_id"], name: "index_users_on_company_department_id"
t.index ["email"], name: "index_users_on_email", unique: true
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end
add_foreign_key "users", "company_departments"
end
会社部門モデル:
class CompanyDepartment < ApplicationRecord
has_many :users
end
ユーザーモデル:
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
belongs_to :company_department, optional: true
end
私は何をしようとしているのでしょうか?
Company Division テーブルのレコードを、Devise サインアップ フォームの [Department] フィールドのドロップダウン オプションのリストとして利用できるようにしたいと考えています。
観察:
サインアップ フォームは機能していますが、会社部門のデータが User テーブルに保存されていないことがわかりました。
ただし、Rails コンソールに移行し、以下のクエリを使用してバックエンドから変更を加えようとすると、部門データは以下のように User テーブルに正常に保存されます。
User.create!(user_name: "abc", password: 123456, password_confirmation: 123456, company_department_id: 3
思考プロセス
これは検証に関連するものだと思います。したがって、以下のようにすべてのユーザー モデル属性をホワイトリストに登録したことを確認しました。
アプリケーションコントローラー:
class ApplicationController < ActionController::Base
include DeviseWhitelist
end
ホワイトリストへの懸念を工夫する
module DeviseWhitelist
extend ActiveSupport::Concern
included do
before_action :configure_permitted_parameters, if: :devise_controller?
end
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: [:user_name, :user_identification_number, :user_employment_start_date, :user_DOB, :user_present__job_title, :user_department, :user_employment_category, :user_office_working_preference, :user_social_status, :user_present_office_location, :user_present_working_shift, :user_basic_pay, :user_gross_pay, :user_appraisal_rating, :user_last_salary_revision_date, :user_appraisal_comments, :user_contact, :user_personalemail, :user_permanent_address, :user_manager, :user_sup1, :user_sup2, :user_sup3, :user_sup4, :user_permanent_illness, :user_phstatus, :user_companyname, :user_skill_category, :user_account_status, **:company_department_id**])
devise_parameter_sanitizer.permit(:account_update, keys: [:user_name, :user_identification_number, :user_employment_start_date, :user_DOB, :user_present__job_title, :user_department, :user_employment_category, :user_office_working_preference, :user_social_status, :user_present_office_location, :user_present_working_shift, :user_basic_pay, :user_gross_pay, :user_appraisal_rating, :user_last_salary_revision_date, :user_appraisal_comments, :user_contact, :user_personalemail, :user_permanent_address, :user_manager, :user_sup1, :user_sup2, :user_sup3, :user_sup4, :user_permanent_illness, :user_phstatus, :user_companyname, :user_skill_category, :user_account_status, **:company_department_id**])
end
end
以下は私がサインアップに使用しているフォームです。デフォルトでは、部門の追加選択フィールドを備えた新しい登録フォームを考案します。
新規ユーザー/サインアップフォームを工夫する
<h2>Sign up</h2>
<%= 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 :email %><br />
<%= f.email_field :email, autofocus: true, autocomplete: "email" %>
</div>
<div class="field">
<%= f.label :password %>
<% if @minimum_password_length %>
<em>(<%= @minimum_password_length %> characters minimum)</em>
<% end %><br />
<%= f.password_field :password, autocomplete: "new-password" %>
</div>
<div class="field">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation, autocomplete: "new-password" %>
</div>
<div class="field">
<%= f.label :user_department %><br />
<%= f.collection_select(:user_department, CompanyDepartment.all, :id, :department_name) %>
</div>
<div class="actions">
<%= f.submit "Sign up" %>
</div>
<% end %>
<%= render "devise/shared/links" %>
部門データが保存されない理由が理解できず、これに関してサポートを求めたいと考えました。ありがとう。
以下では、POST リクエストが開始されると、パラメーターは正しくキャプチャされますが、部門の詳細は保存されないことがわかります。
解決策
company_Department_id を更新しようとしているので、次のようにします。
f.collection_select(:company_department_id ...
2 つの異なる属性を丸で囲みました。コンソールでは正しい属性を使用していますが、フォーム内の別の属性である user_Department は実際には更新されます。