【问题标题】:Rails Undefined Method Error for nil:NilClass用于 nil:NilClass 的 Rails 未定义方法错误
【发布时间】:2017-09-06 14:24:01
【问题描述】:

所以在我的 rails 应用程序中,我的用户拥有不同的权限。当有人登录时,一切正常。但是,当没有人登录时,我收到以下错误:

Undefined method 'editor?' for nil:NilClass

def require_editor
    redirect_to '/error' unless current_user.editor? || current_user.admin?
end

我想我完全理解为什么会发生这种情况:因为没有人登录,Rails 试图弄清楚他们拥有什么角色,并且因为没有人登录它没有角色,Rails 不知道它是否是否应该显示页面。

我的问题是:如何为未登录的人设置默认角色,并将他们发送到显示他们没有权限的错误页面?

【问题讨论】:

  • 其实current_user 只是nilnil 不会响应editor?admin?nil 是 Ruby 描述“无”的方式。但是“有人没有记录它”并不是什么都没有。那nothing is something(顺便说一句讲得很好)。使用对象代替缺少的对象被称为Null Object pattern,这是解决此问题的一种优雅方法。 current_user 来自哪里?你在用设计吗?
  • @Stefan:哈,我知道 Sandi Metz 会说“什么都不是”。而且,当然,是她 :)

标签: ruby-on-rails ruby


【解决方案1】:

我通常会这样做:

class ApplicationController

  def current_user_or_guest
    current_user || Guest.new
  end

  class Guest
    def editor?
      false
    end

    def admin?
      false
    end
  end
end

那么简单

def require_editor
  redirect_to '/error' unless current_user_or_guest.editor? || current_user_or_guest.admin?
end

这可以通过使用CanCanCan 并从控制器中提取授权逻辑来简化。设置了 cancan 功能后,控制器代码通常如下所示:

def require_editor
  redirect_to '/error' unless can?(:edit, MyThing)
end

【讨论】:

  • 这个!提取授权逻辑是最好的方法。从一些条件句开始太容易,后来变得更糟。
【解决方案2】:
def require_editor
    redirect_to '/error' unless current_user && (current_user.editor? || current_user.admin?)
end

您当前正在对 nil 对象调用 editor?,这会引发错误。通过使用上述技术,您首先检查以确保current_user 不是nil,然后检查current_user(如果存在),如果不存在,则返回false 并重定向到/error URL。

【讨论】:

  • 这被称为短路,它是一个重要的编程概念:当评估 and 时:它在第一个 false 处停止。示例:false && raise "Error" 不会引发错误。在评估 or 时,它会在第一个 true 之后停止。
【解决方案3】:

在您的 ApplicationController 中创建一个重定向到错误页面的方法,然后仅在您希望确保用户登录的操作上添加 before_action

应用控制器

def require_editor
  unless current_user && (current_user.editor? || current_user.admin?)
    redirect_to '/error' 
  end
end

控制器你想引发这个错误

class Controller < ApplicationController
  before_action :require_editor
  def new

  end
end 

如果您使用的是 devise gem,则需要使用 callback/filter 进行身份验证

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多