未初始化的常量 Home——由 CanCanCan 为非数据库支持的资源抛出
uninitialized constant Home -- thrown by CanCanCan for non-db backed resource
我正在使用 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]
有效。页面加载非常顺利。
所以我想真正的问题是,如何 authorize/lock 关闭不是 ActiveRecord 模型的资源?
问题似乎源于我尝试 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
中进行硬编码。
我真正想做的只是检查用户当前是否登录,但由于 w/e 原因,所有 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>
如果您对我如何实现这一点有任何建议,请发表评论或写一个新答案,我会接受。在那之前,我想这将不得不做:(
我在关于 managing Non-Restful Controllers 的 CanCanCan wiki 中找到了这种方法的基础。
我正在使用 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]
有效。页面加载非常顺利。
所以我想真正的问题是,如何 authorize/lock 关闭不是 ActiveRecord 模型的资源?
问题似乎源于我尝试 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
中进行硬编码。
我真正想做的只是检查用户当前是否登录,但由于 w/e 原因,所有 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>
如果您对我如何实现这一点有任何建议,请发表评论或写一个新答案,我会接受。在那之前,我想这将不得不做:(
我在关于 managing Non-Restful Controllers 的 CanCanCan wiki 中找到了这种方法的基础。