Rails:devise_invitable,表单验证错误:false:FalseClass 的未定义方法 'errors'
Rails: devise_invitable, form validation errors: undefined method 'errors' for false:FalseClass
我使用 Devise 和 devise_invitable
gem 来管理和邀请用户/成员加入我的 Rails 应用程序。我在表单验证方面遇到了一些问题。我的邀请表中有两个字段,一个用于 name
,另一个用于 recipient_email
。 名称是可选的。当我单击提交按钮时 - 无论表单是否有效,例如当两个字段都为空时 - 我收到以下错误:
undefined method `errors' for false:FalseClass
错误指向我的 invitations_controller
create
操作。此方法如下所示:
def create
@user = User.find_by(email: invite_params[:email])
@team = Team.find_by(id: params[:team_id])
already_invited = false
# Check if the user already s invited to the team.
@team.invitations.each do |invitation|
if @user && invitation.recipient_email.eql?(@user.email)
already_invited = true
end
end
if already_invited
redirect_to edit_team_path(@team), notice: "User already invited"
else
# The app crashes here
super
end
end
我还自定义了这两个devise_invitable
方法:after_invite_path_for
和invite_resource(&block)
。很大程度上基于 this tutorial. 它们看起来像这样:
def after_invite_path_for(resource)
team = Team.find_by_id(params[:team_id])
edit_team_path(team)
end
def invite_resource(&block)
@user = User.find_by(email: invite_params[:email])
@team = Team.find_by(id: params[:team_id])
if @user && @user.email != current_user.email
token = Digest::SHA1.hexdigest([Time.now, rand].join)
@user.invite_existing_user!(@user, current_user, token)
member = @team.members.find_by(user_id: current_or_guest_user.id)
invitation = @team.invitations.build(invitation_token: token, member_id: member.id, recipient_email: invite_params[:email])
invitation.save
@user
else
@user = resource_class.invite!(invite_params, current_inviter, &block)
member = @team.members.find_by(user_id: current_or_guest_user.id)
invitation = @team.invitations.build(invitation_token: @user.raw_invitation_token, member_id: member.id, recipient_email: invite_params[:email])
invitation.save
end
end
我有四个相关模型,User
(被邀请的实体),Team
每个用户可以是 Member
(加入 table)多个Team
。我还有一个自定义 Invitation
模型,每个 Team
可以有很多邀请,我用它来列出为特定团队发送的邀请。邀请功能以前有效,但当表单无效时我遇到了一些问题,例如当两个字段都为 empty
时。为了解决这个问题,我尝试在 Devise.rb
:
中启用它
config.validate_on_invite = true
在我的 User
模型中有以下内容:
devise [...], :invitable, validate_on_invite: true
在我的用户模型中我也有这个:
validates_presence_of :name
validates_presence_of :email
在我的自定义 Invitation
模型中,我有这个:
validates_presence_of :recipient_email
我之前遇到的问题是 invite_resource
被调用,尽管输入无效,我会为我的团队创建一个新的自定义 Invitation
资源。
在错误情况下我想要的只是:
- 不要创建或发送邀请
- 显示错误信息
如何在使用 devise_invitable
时让它工作?
您正在从自定义 invite_resource
实施中返回 false
。基本控制器调用此方法并期望返回一个 ActiveRecord 模型实例,然后对其进行检查 errors
。但是您要返回 false
,因此它会尝试执行 false.errors
- 因此您在调用 super
.
时会看到问题
见第 27 行:
...invite_resource
的默认实现位于:
...相对于您的复杂实现:
def invite_resource(&block)
@user = User.find_by(email: invite_params[:email])
@team = Team.find_by(id: params[:team_id])
if @user && @user.email != current_user.email
token = Digest::SHA1.hexdigest([Time.now, rand].join)
@user.invite_existing_user!(@user, current_user, token)
member = @team.members.find_by(user_id: current_or_guest_user.id)
invitation = @team.invitations.build(invitation_token: token, member_id: member.id, recipient_email: invite_params[:email])
invitation.save
@user
else
@user = resource_class.invite!(invite_params, current_inviter, &block)
member = @team.members.find_by(user_id: current_or_guest_user.id)
invitation = @team.invitations.build(invitation_token: @user.raw_invitation_token, member_id: member.id, recipient_email: invite_params[:email])
invitation.save
end
end
请注意,上述 else
案例的计算结果为 invitation.save
,对于验证错误,该结果将为 false
。您忘记了上述 else
案例中出现的 @user
声明。稍微擦干一下代码,例如如下(风格上这可能不符合每个人的口味):
def invite_resource(&block)
@user = User.find_by(email: invite_params[:email])
@team = Team.find_by(id: params[:team_id])
invitation = if @user && @user.email != current_user.email
token = Digest::SHA1.hexdigest([Time.now, rand].join)
@user.invite_existing_user!(@user, current_user, token)
member = @team.members.find_by(user_id: current_or_guest_user.id)
@team.invitations.build(invitation_token: token, member_id: member.id, recipient_email: invite_params[:email])
else
@user = resource_class.invite!(invite_params, current_inviter, &block)
member = @team.members.find_by(user_id: current_or_guest_user.id)
@team.invitations.build(invitation_token: @user.raw_invitation_token, member_id: member.id, recipient_email: invite_params[:email])
end
invitation.save
@user
end
这至少应该修复你的 undefined method
异常,尽管它会忽略 invitation
上的任何验证错误(这里按顺序是 save!
,整个内容都包含在 User.transaction do...
以保持所有这些邀请的原子性?)。
我使用 Devise 和 devise_invitable
gem 来管理和邀请用户/成员加入我的 Rails 应用程序。我在表单验证方面遇到了一些问题。我的邀请表中有两个字段,一个用于 name
,另一个用于 recipient_email
。 名称是可选的。当我单击提交按钮时 - 无论表单是否有效,例如当两个字段都为空时 - 我收到以下错误:
undefined method `errors' for false:FalseClass
错误指向我的 invitations_controller
create
操作。此方法如下所示:
def create
@user = User.find_by(email: invite_params[:email])
@team = Team.find_by(id: params[:team_id])
already_invited = false
# Check if the user already s invited to the team.
@team.invitations.each do |invitation|
if @user && invitation.recipient_email.eql?(@user.email)
already_invited = true
end
end
if already_invited
redirect_to edit_team_path(@team), notice: "User already invited"
else
# The app crashes here
super
end
end
我还自定义了这两个devise_invitable
方法:after_invite_path_for
和invite_resource(&block)
。很大程度上基于 this tutorial. 它们看起来像这样:
def after_invite_path_for(resource)
team = Team.find_by_id(params[:team_id])
edit_team_path(team)
end
def invite_resource(&block)
@user = User.find_by(email: invite_params[:email])
@team = Team.find_by(id: params[:team_id])
if @user && @user.email != current_user.email
token = Digest::SHA1.hexdigest([Time.now, rand].join)
@user.invite_existing_user!(@user, current_user, token)
member = @team.members.find_by(user_id: current_or_guest_user.id)
invitation = @team.invitations.build(invitation_token: token, member_id: member.id, recipient_email: invite_params[:email])
invitation.save
@user
else
@user = resource_class.invite!(invite_params, current_inviter, &block)
member = @team.members.find_by(user_id: current_or_guest_user.id)
invitation = @team.invitations.build(invitation_token: @user.raw_invitation_token, member_id: member.id, recipient_email: invite_params[:email])
invitation.save
end
end
我有四个相关模型,User
(被邀请的实体),Team
每个用户可以是 Member
(加入 table)多个Team
。我还有一个自定义 Invitation
模型,每个 Team
可以有很多邀请,我用它来列出为特定团队发送的邀请。邀请功能以前有效,但当表单无效时我遇到了一些问题,例如当两个字段都为 empty
时。为了解决这个问题,我尝试在 Devise.rb
:
config.validate_on_invite = true
在我的 User
模型中有以下内容:
devise [...], :invitable, validate_on_invite: true
在我的用户模型中我也有这个:
validates_presence_of :name
validates_presence_of :email
在我的自定义 Invitation
模型中,我有这个:
validates_presence_of :recipient_email
我之前遇到的问题是 invite_resource
被调用,尽管输入无效,我会为我的团队创建一个新的自定义 Invitation
资源。
在错误情况下我想要的只是:
- 不要创建或发送邀请
- 显示错误信息
如何在使用 devise_invitable
时让它工作?
您正在从自定义 invite_resource
实施中返回 false
。基本控制器调用此方法并期望返回一个 ActiveRecord 模型实例,然后对其进行检查 errors
。但是您要返回 false
,因此它会尝试执行 false.errors
- 因此您在调用 super
.
见第 27 行:
...invite_resource
的默认实现位于:
...相对于您的复杂实现:
def invite_resource(&block)
@user = User.find_by(email: invite_params[:email])
@team = Team.find_by(id: params[:team_id])
if @user && @user.email != current_user.email
token = Digest::SHA1.hexdigest([Time.now, rand].join)
@user.invite_existing_user!(@user, current_user, token)
member = @team.members.find_by(user_id: current_or_guest_user.id)
invitation = @team.invitations.build(invitation_token: token, member_id: member.id, recipient_email: invite_params[:email])
invitation.save
@user
else
@user = resource_class.invite!(invite_params, current_inviter, &block)
member = @team.members.find_by(user_id: current_or_guest_user.id)
invitation = @team.invitations.build(invitation_token: @user.raw_invitation_token, member_id: member.id, recipient_email: invite_params[:email])
invitation.save
end
end
请注意,上述 else
案例的计算结果为 invitation.save
,对于验证错误,该结果将为 false
。您忘记了上述 else
案例中出现的 @user
声明。稍微擦干一下代码,例如如下(风格上这可能不符合每个人的口味):
def invite_resource(&block)
@user = User.find_by(email: invite_params[:email])
@team = Team.find_by(id: params[:team_id])
invitation = if @user && @user.email != current_user.email
token = Digest::SHA1.hexdigest([Time.now, rand].join)
@user.invite_existing_user!(@user, current_user, token)
member = @team.members.find_by(user_id: current_or_guest_user.id)
@team.invitations.build(invitation_token: token, member_id: member.id, recipient_email: invite_params[:email])
else
@user = resource_class.invite!(invite_params, current_inviter, &block)
member = @team.members.find_by(user_id: current_or_guest_user.id)
@team.invitations.build(invitation_token: @user.raw_invitation_token, member_id: member.id, recipient_email: invite_params[:email])
end
invitation.save
@user
end
这至少应该修复你的 undefined method
异常,尽管它会忽略 invitation
上的任何验证错误(这里按顺序是 save!
,整个内容都包含在 User.transaction do...
以保持所有这些邀请的原子性?)。