修改Devise_invitable的invite_key_fields实现带额外字段的邀请
问题解决:Devise_invitable邀请时额外字段无法保存及学生档案关联
核心问题排查
- User模型默认角色错误:
set_default_role方法使用了未在enum中定义的:user角色,导致角色赋值失败 - 邀请参数未完全放行:
configure_permitted_parameters仅允许部分字段,且创建AlunoProfile时未关联用户ID - 视图渲染逻辑问题:
resource.class.invite_key_fields.each循环会重复渲染邮箱字段,干扰参数提交 - 学生档案关联缺失:创建AlunoProfile时未绑定对应的User记录
分步修复方案
1. 修正User模型默认角色
修改User模型的默认角色逻辑,使用enum中已定义的角色:
class User < ApplicationRecord has_many :user_aulas has_many :aulas, through: :user_aulas has_many :bookings has_one :aluno_profile devise :invitable, :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable, invite_for: 2.weeks enum role: [:aluno, :professor, :admin] after_initialize :set_default_role, :if => :new_record? def set_default_role self.role ||= :aluno # 使用enum中存在的角色作为默认值 end def full_name "#{first_name} #{last_name}" end end
2. 调整邀请控制器参数与档案创建逻辑
更新Users::InvitationsController,确保参数正确传递并关联用户:
class Users::InvitationsController < Devise::InvitationsController before_action :configure_permitted_parameters def create super do |resource| # 角色确认后创建关联的学生档案 if resource.role == "aluno" resource.create_aluno_profile(aluno_profile_params) end end end private def aluno_profile_params params.require(:user).permit( :morada, :birthdate, :nif, :numero_utente, :cartao_cidadao, :validity, :contacto, :encarregado_educação, :grau_parentesco, :contacto_emergencia, :aulas, :horario_preferencial, :recolha_dados, :fotografias_captadas ) end protected def configure_permitted_parameters # 放行所有需要传递的用户及学生档案字段 devise_parameter_sanitizer.permit(:invite, keys: [ :first_name, :last_name, :role, :morada, :birthdate, :nif, :numero_utente, :cartao_cidadao, :validity, :contacto, :encarregado_educação, :grau_parentesco, :contacto_emergencia, :aulas, :horario_preferencial, :recolha_dados, :fotografias_captadas ]) end end
3. 修复邀请视图渲染逻辑
移除循环渲染,避免重复生成表单元素:
<h2 class="mx-3 mt-2"><%= t "devise.invitations.new.header" %></h2> <%= simple_form_for(resource, as: resource_name, url: invitation_path(resource_name), html: { method: :post }) do |f| %> <%= f.error_notification %> <div class="form-inputs mx-3"> <%= f.input :first_name, input_html: {placeholder: "John"} %> <%= f.input :last_name, input_html: {placeholder: "Doe"} %> <%= f.input :email, input_html: {placeholder: "example@example.com"} %> <%= f.input :role, as: :select, collection: User.roles.keys, prompt: "Selecionar uma opção", input_html: {class: "form-select"} %> <%# 可选:根据选中的角色动态显示学生档案字段 %> <% if f.object.role == "aluno" %> <%= f.input :morada %> <%= f.input :birthdate, as: :date %> <%# 其他学生档案字段按需添加 %> <% end %> </div> <div class="form-actions mx-3"> <%= f.button :submit, t("devise.invitations.new.submit_button"), class: 'btn btn-primary' %> </div> <% end %>
4. 确认数据库字段完整性
检查并添加必要的数据库字段:
users表需包含first_name, last_name, role字段aluno_profiles表需包含所有学生档案字段及user_id外键
示例迁移文件:
# 添加用户字段 class AddFieldsToUsers < ActiveRecord::Migration[7.0] def change add_column :users, :first_name, :string add_column :users, :last_name, :string add_column :users, :role, :string, default: "aluno" end end # 创建学生档案表 class CreateAlunoProfiles < ActiveRecord::Migration[7.0] def change create_table :aluno_profiles do |t| t.references :user, null: false, foreign_key: true t.string :morada t.date :birthdate t.string :nif # 其他学生档案字段依次添加 t.timestamps end end end
关键说明
- 使用
resource.create_aluno_profile自动关联用户ID,无需手动传递 - 确保
configure_permitted_parameters放行所有需要的字段,包括学生档案字段 - 移除视图中的循环渲染,避免表单元素重复导致参数提交异常
内容的提问来源于stack exchange,提问作者jccsag
相关产品推荐
相关产品推荐

