Ruby on rails Rails验证仍在启动,除非选项评估为true
我在我的应用程序中使用Ruby on rails Rails验证仍在启动,除非选项评估为true,ruby-on-rails,ruby-on-rails-3,validation,devise,devise-invitable,Ruby On Rails,Ruby On Rails 3,Validation,Devise,Devise Invitable,我在我的应用程序中使用designe\u invitable,允许用户发送邀请。我意识到一个糟糕的情况,一个用户被邀请了,但忽略了邀请,然后返回应用程序自己注册。由于designe\u invitable通过使用为邀请提供的电子邮件地址创建新的用户来处理邀请,因此我在电子邮件字段上的唯一性验证将导致Rails投诉,告诉用户电子邮件地址已被占用 我想写一些逻辑来处理这个案子。我看到了两条路径——要么找到一种方法来检测并销毁先前创建的用户并允许创建新用户,要么检测用户被邀请并执行另一个流。我决定实施
designe\u invitable
,允许用户发送邀请。我意识到一个糟糕的情况,一个用户被邀请了,但忽略了邀请,然后返回应用程序自己注册。由于designe\u invitable
通过使用为邀请提供的电子邮件地址创建新的用户来处理邀请,因此我在电子邮件字段上的唯一性验证将导致Rails投诉,告诉用户电子邮件地址已被占用
我想写一些逻辑来处理这个案子。我看到了两条路径——要么找到一种方法来检测并销毁先前创建的用户并允许创建新用户,要么检测用户被邀请并执行另一个流。我决定实施第二个选项,因为如果可能的话,我仍然希望使用邀请
我有限的经验让我质疑我所写的东西是否有效,但我不能完全测试它,因为邮件上的Rails验证被触发了。我已确保Desive的:validable
模块处于非活动状态。我创建了一个(我认为)将检测用户是否被邀请的方法,在这种情况下,应该跳过唯一性验证
#user.rb
...
validates :email, uniqueness: true, unless: :was_invited?
...
def was_invited?
if self.invitation_sent_at.present? && self.sign_in_count == 0
true
else
false
end
end
FWIW,我最初是用速记法写的,而不是用if/else,但是我想非常明确地找出bug/失败
希望表单通过验证后,create
操作将检测用户的邀请状态,如果他们被邀请,则将他们重定向到accept\u user\u invitation\u路径
。再一次,我还没有能够真正测试它,因为我无法绕过验证
#registrations_controller.rb
def create
if User.find_by_email(params[:email])
@existing_user = User.find_by_email(params[:email])
@existing_user.save(validate: false)
if @existing_user.was_invited?
redirect_to accept_user_invitation_path(:invitation_token => @existing_user.invitation_token)
end
else
super
end
end
你会看到,我还添加了.save(validate:false)
来尝试在那里短路,但它甚至没有走多远
如果我完全注释掉电子邮件验证,只是为了测试其余的逻辑/流程,我会收到一个PG错误,抱怨唯一性,因为电子邮件地址上有一个索引-我不想简单地为了测试这个方法而把这一切都拆开
我已经试着处理这个问题好几个小时了,我不知所措——任何帮助都是感激的。如果您想查看其他代码,请告诉我 也许你应该给你的控制员更多的责任
如果找到用户,请使用该用户,否则请创建一个新用户。假设您的表单显示为http://yourapp/users/new
,在路线中将其更改为http://yourapp/users/new/:email
,让用户在进入表单之前输入电子邮件
def new
@existing_user = User.find_by_email("#{params[:email]}.#{params[:format]}") || User.new
if @existing_user.was_invited? # will only work for existing user
redirect_to accept_user_invitation_path(:invitation_token => @existing_user.invitation_token)
else
render 'new'
end
end
def create
# do maybe something before saving
if @existing_user.save(user_params)
# do your magic
else
render 'new', notice: "Oops, I didn't save"
end
end
查看重定向:
redirect_to accept_user_invitation_path(:invitation_token => @existing_user.invitation_token)
我可以看到没有返回
,这意味着如果调用该重定向,您应该会得到一个AbstractController::DoubleRenderError
错误,因为父控制器的创建
方法应该尝试呈现新
视图
从这一点上,我猜您用于查找现有用户的查询实际上并没有返回结果,可能是因为您使用的是params[:email]
,而如果您使用的是默认视图或格式正确的表单,则应该是params[:user][:email]
,我只是为了以防万一,尝试了这个方法,但这并没有解决我的问题。对于重构create方法,这里有一些有用的东西,但首先也是最重要的是问题所在-应用程序无法访问此代码,因为验证正在表单上运行,唯一性验证失败。我必须先通过它。在这种情况下,您应该将第一行带到控制器中的“new”操作,并为@existing\u user运行表单。那会彻底解决你的问题。查看已编辑的版本如果是用户,是否确定。通过电子邮件查找(参数[:email])
是否为真?似乎从未到达if
中的代码。你能从你的日志中发布你的表格和提交的参数吗?(不应该是params[:user][:email]
?)您在创建操作中所做的事情很奇怪:您正在获取一个现有用户,然后对其调用save
,这是没有用的,因为您没有更改任何内容。@misha-是的,这就是问题所在!我(愚蠢地)执行了一个正确构造的查询,丢失了[:user]
部分,因此没有找到用户,因此跳过了其余的逻辑。您是对的,保存基本上是无用的-我正在尝试使用validate:false
来通过电子邮件验证,但这是不必要的,因为在修复查询后,一切都很顺利。谢谢你的评论!你完全正确-我没有正确地查询散列以获取用户
,因此它正在搜索一封NULL的电子邮件,因此没有正确地捕获其余的逻辑。现在一切都很好,谢谢你!