两天后,我自己无法解决这个问题。看起来它应该很简单,但我遗漏了一些东西。我正在创建一个包含帖子和作者的简单博客。作者有一个布尔管理列。
现在给我一个错误的行是我检查权限以显示帖子中的编辑按钮。当前错误是:
帖子中的NoMethodError#show
显示...... / posts / show.html.erb,其中第18行引发:
#
的未定义方法`stringify_keys'文章/ show.html.rb
<% if @author.can? :update, @post %>
<p><%= link_to 'Edit', edit_post_path(@post), :class => 'btn' %> <%= link_to 'Destroy', @post, confirm: 'Are you sure?', method: :delete %></p>
<% end %>
application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery
rescue_from CanCan::AccessDenied do |exception|
redirect_to root_url, :alert => exception.message
end
helper_method :current_author
def current_user
@current_ability ||= Author.new(current_author)
end
end
ability.rb
class Ability
include CanCan::Ability
def initialize(author)
author ||= Author.new # guest user (not logged in)
if author.admin?
can :manage, :all
else
can :read, :all
end
end
end
另外,据我所知,CanCan正确地包含在gem文件中。
答案 0 :(得分:1)
两件事。
首先,您需要在控制器中使用current_user
方法,cancan可以依赖该方法。如果你没有,你可以
current_user
到您的current_whatever
方法或@ability = Ability.new(current_whatever)
之类的功能,并在您的观看次数中调用您生成的can?
个功能(例如@ability.can? :edit, @post
)。其次,您的Ability
在第4行和第5行都使用current_author
,但您的current_author
方法中没有initialize
。但是你有author
。如果没有Author
对象可用/给予该能力的初始化程序,则使用非持久作者(而不是AuthorAbility,除非您的AuthorAbility是current_user
返回的内容或initialize
能力作为参数)。像这样:
class Ability
include CanCan::Ability
def initialize(author)
author ||= Author.new # guest user (not logged in)
if author.admin?
can :manage, :all
else
can :read, :all
end
end
end
根据评论进行编辑以使其更简单:
理想情况下,您在应用程序控制器中放置了current_user
方法,并在视图中将其作为帮助程序使用(因为您可能希望根据登录用户有条件地显示/隐藏/更改视图中的内容)。
class ApplicationController < ActionController::Base
helper_method :current_user
def current_user
# return the currently logged in user record
end
end
如果您不熟悉,我建议您查看身份验证宝石。 Devise还介绍了这一点,authlogic在其操作方法和示例应用程序中对此进行了描述。如果您从头开始进行身份验证,则只需根据会话返回用户。
编辑2.你实际上需要了解你的所作所为,目前恕我直言。你在这里做得有点混乱;-)
问题1:current_user
需要返回当前作者/用户登录(不是内容或后退用户或其他内容)或nil
如果没有记录作者在。所以你可以例如在您的视图中执行<% if current_user %>
。 @current_ability ||= Author.new(current_author)
是完全错误的。能力类的后退需要保留在能力类中,因为cancan的方法只能应用于对象而不能应用于nil
。因此,使用author ||= Author.new
,即使没有作者登录,也要确保有对象(在这种情况下current_author
会返回nil
)。
问题2:helper_method :current_author
实际上什么也没做,因为应用程序控制器中没有current_author
方法。您需要以某种方式定义current_author
。
问题3:在您看来,您在can?
的实例上调用了Author
这是错误的。 can?
是Ability
的一种方法。因此,您需要使用@my_ability.can?
,其中@my_ability是例如Ability.new(Author.first)
。如果您需要使用多种功能或自定义某些功能,则会使用此功能,而这种情况并非如此,所以只需在没有接收器的情况下直接使用can?
(例如@author.can?
)。
出于测试目的,我将创建以下内容:
class ApplicationController < ActionController::Base
helper_method :current_user # as defined below...
def current_user
# Return a static user here, for testing purposes,
# like @current_user = User.first or Author.first
end
end
所以你的current_user
会返回一个有效的用户(我希望你至少需要在数据库中存储一个用户),然后才能解决能力问题。如果您的能力有效,则可以实施身份验证。作为初学者,我要么坚持authlogic或devise。