Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ruby-on-rails-3/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails Rails验证仍在启动,除非选项评估为true_Ruby On Rails_Ruby On Rails 3_Validation_Devise_Devise Invitable - Fatal编程技术网

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的电子邮件,因此没有正确地捕获其余的逻辑。现在一切都很好,谢谢你!