未初始化的常量Home - 由CanCanCan为非db支持的资源抛出

时间:2016-11-01 17:49:28

标签: ruby-on-rails routing ruby-on-rails-5 cancancan

我使用CanCanCan进行授权。基本上我想要发生的是未登录的用户可以访问Home#Index,但他们需要登录Home#Dashboard

我有这条路线:

get 'dashboard', to: 'home#dashboard', as: :dashboard

这是我的HomeController

class HomeController < ApplicationController
  authorize_resource except: [:index]
  skip_authorization_check only: [:index]
  layout 'marketing', only: [:index]

  def index
  end

  def dashboard
  end
end

这是我的application_controller.rb

class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception
  before_action :configure_permitted_parameters, if: :devise_controller?
  check_authorization :unless => :devise_controller?

  rescue_from CanCan::AccessDenied do |exception|
    respond_to do |format|
      format.json { head :forbidden }
      format.html { redirect_back(fallback_location: root_path, flash: { danger: exception.message }) }
    end
  end

  protected

  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:accept_invitation, keys: [:first_name, :last_name, :phone])
  end
end

然而,当我转到/dashboard时,这是我得到的错误:

NameError - uninitialized constant Home:
  activesupport (5.0.0.1) lib/active_support/dependencies.rb:550:in `load_missing_constant'
  activesupport (5.0.0.1) lib/active_support/dependencies.rb:203:in `const_missing'
  activesupport (5.0.0.1) lib/active_support/inflector/methods.rb:268:in `block in constantize'
  activesupport (5.0.0.1) lib/active_support/inflector/methods.rb:266:in `constantize'
  activesupport (5.0.0.1) lib/active_support/core_ext/string/inflections.rb:66:in `constantize'

导致这种情况的原因是什么?

修改1

经过一些调试后,我现在意识到这似乎与我authorizing的动作不受ActiveRecord资源支持这一事实有关。

换句话说,一旦我将:dashboard添加到exception列表中,就像这样:

  authorize_resource except: [:index, :dashboard]
  skip_authorization_check only: [:index, :dashboard]

有效。该页面像魅力一样加载。

所以我猜真正的问题是,如何授权/锁定不是ActiveRecord模型的资源?

1 个答案:

答案 0 :(得分:0)

似乎问题源于我尝试authorize_resource的资源不是ActiveRecord模型支持的资源。

所以我必须从控制器的开头删除authorize_resource,然后authorize!删除每个单独的操作。然后我必须将该规则添加到ability.rb

现在我的HomeController看起来像这样:

class HomeController < ApplicationController
  skip_authorization_check only: [:index]
  layout 'marketing', only: [:index]


  def index
  end

  def dashboard
    authorize! :read, :dashboard
  end
end

然后,在我的ability.rb中,我有这个:

class Ability
  include CanCan::Ability

  def initialize(user)
    user ||= User.new # guest user (not logged in)

    can :manage, User, id: user.id
    can :read, :dashboard if user.has_any_role? :admin, :coach, :player
  end
end

我必须在我的数据库中的所有roles中进行硬编码。

我真正想要做的只是检查一下用户当前是否已登录,但由于这个原因,它在所有user_signed_in?项检查中都失败了。

理想情况下,我喜欢做类似的事情:

can :read, :dashboard if current_user?

或者:

can :read, :dashboard if user.user_signed_in?

但是这两个都不起作用并且给了我以下错误的变体:

undefined local variable or method `current_user' for #<Ability:0x007faca14db2c8>

或者:

undefined method `user_signed_in?' for #<User:0x007fac86b2a9c8>

如果您对如何实现此目标有任何建议,请发表评论或撰写新答案,我会接受。在那之前,我想这将是必须的:(

我在CanCanCan维基中找到的关于managing Non-Restful Controllers的这种方法的基础。