Devise Invitable 正在修改现有用户
Devise Invitable is modifying existing users
上下文
我正在使用 devise_invitable 允许用户(具有管理员角色)在我的应用程序中注册另一个用户。
用户对象有电子邮件、密码、令牌(随机字符串)、角色(也是字符串)和关联的HealthRecord对象有姓名、姓氏、dni(个人 ID)以及一些额外信息
问题
出于某种原因,当我输入现有电子邮件时,出现错误(这是为了验证),但它也破坏了与拥有该现有电子邮件的用户关联的 HealthRecord。
代码
这是我的控制台在尝试使用现有电子邮件创建用户时显示的内容
Started POST "/users/invitation" for ::1 at 2021-11-26 10:04:15 -0300
Processing by Users::InvitationsController#create as HTML
Parameters: {"authenticity_token"=>"[FILTERED]", "user"=>{"email"=>"paciente1@example.com", "role"=>"Paciente", "health_record_attributes"=>{"residencia"=>"Cementerio", "nombre"=>"overriding", "apellido"=>"test", "dni"=>"123456789", "risk"=>"0", "birth"=>"1999-02-12"}}, "commit"=>"Registrar"}
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT ? [["id", 5], ["LIMIT", 1]]
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."email" = ? ORDER BY "users"."id" ASC LIMIT ? [["email", "paciente1@example.com"], ["LIMIT", 1]]
HealthRecord Load (0.1ms) SELECT "health_records".* FROM "health_records" WHERE "health_records"."user_id" = ? LIMIT ? [["user_id", 1], ["LIMIT", 1]]
TRANSACTION (0.1ms) begin transaction
HealthRecord Destroy (0.5ms) DELETE FROM "health_records" WHERE "health_records"."id" = ? [["id", 1]]
TRANSACTION (207.2ms) commit transaction
User Exists? (0.3ms) SELECT 1 AS one FROM "users" WHERE "users"."email" = ? AND "users"."id" != ? LIMIT ? [["email", "paciente1@example.com"], ["id", 1], ["LIMIT", 1]]
HealthRecord Exists? (0.4ms) SELECT 1 AS one FROM "health_records" WHERE "health_records"."dni" = ? LIMIT ? [["dni", "123456789"], ["LIMIT", 1]]
Rendering layout layouts/application.html.erb
Rendering users/invitations/new.html.erb within layouts/application
HealthRecord Load (0.1ms) SELECT "health_records".* FROM "health_records" WHERE "health_records"."user_id" = ? LIMIT ? [["user_id", 5], ["LIMIT", 1]]
↳ app/views/users/invitations/new.html.erb:18
生成新用户的视图
<h2>Registro excepcional</h2>
<%= form_for(setup_user(resource), as: resource_name, url: invitation_path(resource_name), html: { method: :post }) do |f| %>
<% resource.class.invite_key_fields.each do |field| -%>
<div class="field">
<%= f.label field %><br />
<%= f.text_field field, class: 'form-control'%>
</div>
<% end %>
<div class="field">
<%= f.hidden_field :role, :value=>"Paciente"%>
</div>
<%= f.fields_for :health_record do |ff| %>
<div class="field">
<%= ff.hidden_field :residencia, :value=>current_user.health_record.residencia%>
</div>
<div class="field">
<%= ff.label "Nombre" %><br/>
<%= ff.text_field :nombre, class: 'form-control',:required => true%>
</div>
<div class="field">
<%= ff.label "Apellido" %><br/>
<%= ff.text_field :apellido, class: 'form-control',:required => true%>
</div>
<div class="field">
<%= ff.label "DNI" %><br/>
<%= ff.text_field :dni, class: 'form-control',:required => true%>
</div>
<div class="field">
<%= ff.label "Es de riesgo:",:required => true %>
<%= ff.check_box :risk %>
</div>
<div class="field">
<%= ff.label "Fecha de nacimiento:"%><br/>
<%= ff.date_field :birth, class: 'form-control',:required => true%>
</div>
<% end %>
<br/>
<div class="actions">
<%= f.submit "Registrar" %>
</div>
<% end %>
用户模型具有validate_on_invite
class User < ApplicationRecord
devise :invitable, :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable, :authentication_keys => [:token,:email], :validate_on_invite => true
has_many :comprobantes, :dependent => :destroy
has_one :health_record, :dependent => :destroy
has_many :TurnoAsignado, :dependent => :destroy
has_many :TurnoNoAsignado, :dependent => :destroy
validates :email, uniqueness: true
before_save :init
accepts_nested_attributes_for :health_record
def init()
if self.token.nil?
self.token = (rand()*1000000).to_i
end
end
end
HealthRecord 模型
class HealthRecord < ApplicationRecord
belongs_to :user
validates :dni, presence: true
validates :dni, uniqueness: true
validates :nombre, presence: true
validates :apellido, presence: true
validates :birth, presence: true
before_save :upcase_content
def upcase_content
self.nombre=self.nombre.downcase
self.apellido=self.apellido.downcase
self.nombre=self.nombre.split(/ |\_/).map(&:capitalize).join(" ")
self.apellido=self.apellido.split(/ |\_/).map(&:capitalize).join(" ")
end
end
邀请控制器(几乎是默认设置,我只是添加了参数和一个 after_path)
class Users::InvitationsController < Devise::InvitationsController
before_action :configure_permitted_parameters
#Permit the new params here.
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:invite, keys: [
:token,
:role,
health_record_attributes: [
:apellido,
:nombre,
:dni,
:risk,
:birth,
:residencia
]
])
end
def after_invite_path_for(resource)
new_asignado_path(self.resource.id)
end
end
我认为问题可能出在这一行
form_for(setup_user(resource),...
我正在使用助手将用户的 HealthRecord 设置为空(fields_for 需要用户拥有 HealthRecord 才能工作)
module FormHelper
def setup_user(user)
user.health_record ||= HealthRecord.new # ||= means “assign this value unless it already has a value”
user
end
end
也许发生的事情是空的 HealthRecord 不知何故分配给了现有用户?
我通过拦截邀请控制器中创建方法的流程解决了这个问题,通过询问用户电子邮件或 dni 是否存在
def create
@correo = User.find_by(email:params[:user][:email])
@dni = HealthRecord.find_by(dni:params[:user][:health_record_attributes][:dni])
if (@correo.nil? && @dni.nil?) #si no existe mail ni dni
super
else
mensaje="Los siguientes campos ya estan registrados:"
if !(@correo.nil?)
mensaje = mensaje + " email"
end
if !(@dni.nil?)
mensaje = mensaje + " dni"
end
flash[:notice] = mensaje
redirect_to new_user_invitation_path
end
end
虽然可行,但我不确定问题的原因,欢迎任何见解
上下文
我正在使用 devise_invitable 允许用户(具有管理员角色)在我的应用程序中注册另一个用户。
用户对象有电子邮件、密码、令牌(随机字符串)、角色(也是字符串)和关联的HealthRecord对象有姓名、姓氏、dni(个人 ID)以及一些额外信息
问题
出于某种原因,当我输入现有电子邮件时,出现错误(这是为了验证),但它也破坏了与拥有该现有电子邮件的用户关联的 HealthRecord。
代码
这是我的控制台在尝试使用现有电子邮件创建用户时显示的内容
Started POST "/users/invitation" for ::1 at 2021-11-26 10:04:15 -0300
Processing by Users::InvitationsController#create as HTML
Parameters: {"authenticity_token"=>"[FILTERED]", "user"=>{"email"=>"paciente1@example.com", "role"=>"Paciente", "health_record_attributes"=>{"residencia"=>"Cementerio", "nombre"=>"overriding", "apellido"=>"test", "dni"=>"123456789", "risk"=>"0", "birth"=>"1999-02-12"}}, "commit"=>"Registrar"}
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT ? [["id", 5], ["LIMIT", 1]]
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."email" = ? ORDER BY "users"."id" ASC LIMIT ? [["email", "paciente1@example.com"], ["LIMIT", 1]]
HealthRecord Load (0.1ms) SELECT "health_records".* FROM "health_records" WHERE "health_records"."user_id" = ? LIMIT ? [["user_id", 1], ["LIMIT", 1]]
TRANSACTION (0.1ms) begin transaction
HealthRecord Destroy (0.5ms) DELETE FROM "health_records" WHERE "health_records"."id" = ? [["id", 1]]
TRANSACTION (207.2ms) commit transaction
User Exists? (0.3ms) SELECT 1 AS one FROM "users" WHERE "users"."email" = ? AND "users"."id" != ? LIMIT ? [["email", "paciente1@example.com"], ["id", 1], ["LIMIT", 1]]
HealthRecord Exists? (0.4ms) SELECT 1 AS one FROM "health_records" WHERE "health_records"."dni" = ? LIMIT ? [["dni", "123456789"], ["LIMIT", 1]]
Rendering layout layouts/application.html.erb
Rendering users/invitations/new.html.erb within layouts/application
HealthRecord Load (0.1ms) SELECT "health_records".* FROM "health_records" WHERE "health_records"."user_id" = ? LIMIT ? [["user_id", 5], ["LIMIT", 1]]
↳ app/views/users/invitations/new.html.erb:18
生成新用户的视图
<h2>Registro excepcional</h2>
<%= form_for(setup_user(resource), as: resource_name, url: invitation_path(resource_name), html: { method: :post }) do |f| %>
<% resource.class.invite_key_fields.each do |field| -%>
<div class="field">
<%= f.label field %><br />
<%= f.text_field field, class: 'form-control'%>
</div>
<% end %>
<div class="field">
<%= f.hidden_field :role, :value=>"Paciente"%>
</div>
<%= f.fields_for :health_record do |ff| %>
<div class="field">
<%= ff.hidden_field :residencia, :value=>current_user.health_record.residencia%>
</div>
<div class="field">
<%= ff.label "Nombre" %><br/>
<%= ff.text_field :nombre, class: 'form-control',:required => true%>
</div>
<div class="field">
<%= ff.label "Apellido" %><br/>
<%= ff.text_field :apellido, class: 'form-control',:required => true%>
</div>
<div class="field">
<%= ff.label "DNI" %><br/>
<%= ff.text_field :dni, class: 'form-control',:required => true%>
</div>
<div class="field">
<%= ff.label "Es de riesgo:",:required => true %>
<%= ff.check_box :risk %>
</div>
<div class="field">
<%= ff.label "Fecha de nacimiento:"%><br/>
<%= ff.date_field :birth, class: 'form-control',:required => true%>
</div>
<% end %>
<br/>
<div class="actions">
<%= f.submit "Registrar" %>
</div>
<% end %>
用户模型具有validate_on_invite
class User < ApplicationRecord
devise :invitable, :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable, :authentication_keys => [:token,:email], :validate_on_invite => true
has_many :comprobantes, :dependent => :destroy
has_one :health_record, :dependent => :destroy
has_many :TurnoAsignado, :dependent => :destroy
has_many :TurnoNoAsignado, :dependent => :destroy
validates :email, uniqueness: true
before_save :init
accepts_nested_attributes_for :health_record
def init()
if self.token.nil?
self.token = (rand()*1000000).to_i
end
end
end
HealthRecord 模型
class HealthRecord < ApplicationRecord
belongs_to :user
validates :dni, presence: true
validates :dni, uniqueness: true
validates :nombre, presence: true
validates :apellido, presence: true
validates :birth, presence: true
before_save :upcase_content
def upcase_content
self.nombre=self.nombre.downcase
self.apellido=self.apellido.downcase
self.nombre=self.nombre.split(/ |\_/).map(&:capitalize).join(" ")
self.apellido=self.apellido.split(/ |\_/).map(&:capitalize).join(" ")
end
end
邀请控制器(几乎是默认设置,我只是添加了参数和一个 after_path)
class Users::InvitationsController < Devise::InvitationsController
before_action :configure_permitted_parameters
#Permit the new params here.
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:invite, keys: [
:token,
:role,
health_record_attributes: [
:apellido,
:nombre,
:dni,
:risk,
:birth,
:residencia
]
])
end
def after_invite_path_for(resource)
new_asignado_path(self.resource.id)
end
end
我认为问题可能出在这一行
form_for(setup_user(resource),...
我正在使用助手将用户的 HealthRecord 设置为空(fields_for 需要用户拥有 HealthRecord 才能工作)
module FormHelper
def setup_user(user)
user.health_record ||= HealthRecord.new # ||= means “assign this value unless it already has a value”
user
end
end
也许发生的事情是空的 HealthRecord 不知何故分配给了现有用户?
我通过拦截邀请控制器中创建方法的流程解决了这个问题,通过询问用户电子邮件或 dni 是否存在
def create
@correo = User.find_by(email:params[:user][:email])
@dni = HealthRecord.find_by(dni:params[:user][:health_record_attributes][:dni])
if (@correo.nil? && @dni.nil?) #si no existe mail ni dni
super
else
mensaje="Los siguientes campos ya estan registrados:"
if !(@correo.nil?)
mensaje = mensaje + " email"
end
if !(@dni.nil?)
mensaje = mensaje + " dni"
end
flash[:notice] = mensaje
redirect_to new_user_invitation_path
end
end
虽然可行,但我不确定问题的原因,欢迎任何见解