【问题标题】:Why is this view template expected?为什么需要这个视图模板?
【发布时间】:2015-12-26 19:06:41
【问题描述】:

我有一个控制器方法来验证收到带有令牌的链接的用户(参见底部的方法)。我有一个集成测试:

def test
  get login_path('invalid token')     // Login_path routes to the controller method below.
  assert flash[:danger]
  assert_redirected_to root_path
end

此测试产生以下错误(参考get login_path('invalid token')):

ActionView::MissingTemplate: Missing template invitations/login, application/login with {:locale=>[:en], :formats=>[:html], :variants=>[], :handlers=>[:erb, :builder, :raw, :ruby, :coffee, :jbuilder]}. 

视图invitiations/login 确实不存在。但是,考虑到下面的控制器方法,永远不需要这样的视图(它总是重定向到root_path 或呈现profiles/show)。什么可能导致此错误?

控制器方法:

def login
  inv = Invitation.where('email = ?', params[:email])
  if inv
    inv.each do |person|
      if person.authenticated?(:invitation, params[:id])
        @organization = person.organization
        unless @organization.nil?
          render 'profiles/show' and return
        else
          flash[:danger] = "Error"
          redirect_to root_path and return
        end
      end
      flash[:danger] = "Invalid link"
      redirect_to root_path
    end
  else
    flash[:danger] = "Invalid link"
    redirect_to root_path
  end
end

附:该测试过去通过,即直到我重写了控制器方法以适应多个inv(参见Retrieve multiple records with find_by method)。

【问题讨论】:

  • 渲染后你没有返回。只要确保你没有渲染两次。在if-conditional 的每个分支中渲染一次是可以的。
  • 关于可能的错误来源的说明:您迭代了邀请,但 item 变量名为 person。我本来希望该变量被命名为invitation。而invinvitations。遵循这种命名约定将为您省去很多麻烦。

标签: ruby-on-rails ruby model-view-controller integration-testing


【解决方案1】:

您使用if inv - 如果不存在具有匹配电子邮件的邀请,这仍将返回true,因为inv 是一个ActiveRecord 查询对象。但随后 each 什么都不做,即不重定向或显式呈现。将调用默认渲染并期望模板存在。

使用if inv.present? 可以解决此问题。

(另外,您可能希望确保inv 集合仅包含一个结果。在同一请求中多次重定向或呈现会导致错误。)

【讨论】:

  • 或者,将第 14 + 15 行的重定向向上移动一级,即移出each 循环。那么只有当没有被邀请的人符合条件时才会发生这种重定向。
  • 太好了,感谢您的所有建议。有用!希望再问一个关于render 'profiles/show' and return 的问题:我的目标是,当它第一次到达该行时,它会立即呈现该页面并且不会进一步执行控制器方法(我添加了“并返回”的想法,这将照顾好那个)。因为否则,正如您所说,它可能会渲染多次......?我这样做是正确的还是在当前设置下它可能会尝试多次渲染?
  • 如果inv 产生两个person.authenticated?(:invitation, params[:id]) 评估为假的项目,那么您将两次点击第15 行,是的。
  • 希望有帮助!既然您提到您对答案感到满意,请点击该按钮并接受它:)
  • 感谢接受。 8号线没问题。它将在render 语句之后立即中止方法执行并按预期运行。就我个人而言,我永远不会使用and return,而是先找出要做什么,然后让if elsif else end 条件正确呈现或重定向。在您的情况下,我可能会在 inv 中搜索匹配的项目(使用 Enumerable#detect)然后渲染它(如果找到;否则重定向错误)
猜你喜欢
  • 1970-01-01
  • 2020-05-20
  • 1970-01-01
  • 2019-06-22
  • 2018-09-08
  • 1970-01-01
  • 2016-04-30
  • 2014-11-28
  • 1970-01-01
相关资源
最近更新 更多