我使用Devise和devise_inviable
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
的{{1}}(联接表)。我还有一个自定义的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
时如何才能使其工作?
答案 0 :(得分:1)
您从自定义false
实施中返回invite_resource
。基本控制器调用此方法并期望返回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
。您忘记了上述@user
案例中的else
声明。只是稍微干掉那段代码,例如如下(风格上可能不是每个人的口味):
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!
,整个内容都包含在{{1}中保持所有这些邀请原子?)。