Rails:devise_inviable,表单验证错误:未定义的方法'错误' for false:FalseClass

时间:2016-02-06 14:54:34

标签: ruby-on-rails ruby ruby-on-rails-4 devise devise-invitable

我使用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_forinvite_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资源。

在错误情况下我想要的只是:

  1. 不要创建或发送邀请
  2. 显示错误消息
  3. 使用Invitation时如何才能使其工作?

1 个答案:

答案 0 :(得分:1)

您从自定义false实施中返回invite_resource。基本控制器调用此方法并期望返回ActiveRecord模型实例,然后检查errors。但是您返回false,因此它会尝试执行false.errors - 因此您在调用super时会看到问题。

见第27行:

https://github.com/scambra/devise_invitable/blob/master/app/controllers/devise/invitations_controller.rb#L25

...以及invite_resource的默认实现位于:

https://github.com/scambra/devise_invitable/blob/master/app/controllers/devise/invitations_controller.rb#L81

...与您的复杂实施相比:

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}中保持所有这些邀请原子?)。