[英]Problems with CanCan Methods with Rails3 / Devise
After two days, I've not been able to solve this problem on my own. 两天后,我无法自行解决此问题。 It seems like it should be pretty simple, but I'm missing something.
看起来应该很简单,但是我缺少了一些东西。 I'm creating a simple blog with Posts and Authors.
我正在用Posts and Authors创建一个简单的博客。 Authors have a boolean admin column.
作者有一个布尔admin列。
The line that is giving me an error right now is where I check permissions to show the edit button in a post.Current error is: 现在出现错误的行是我检查权限以在帖子中显示编辑按钮的地方。当前错误是:
NoMethodError in Posts#show Posts#show中的NoMethodError
Showing .../posts/show.html.erb where line #18 raised: 在第18行出现的位置显示... / posts / show.html.erb:
undefined method `stringify_keys' for # #的未定义方法`stringify_keys'
posts/show.html.rb posts / 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 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
Also, from what I can tell, CanCan is included in the gem file correctly. 另外,据我所知,CanCan正确包含在gem文件中。
Two things. 两件事情。
First, you need to have a current_user
method in your controller, on which cancan relies. 首先,您需要在控制器中有一个can_can依赖的
current_user
方法。 If you don't have one, you may 如果您没有一个,可以
current_user
to your current_whatever
method or current_user
您current_whatever
方法或 @ability = Ability.new(current_whatever)
and call your can?
@ability = Ability.new(current_whatever)
然后打电话给您can?
's on that generated ability in your views (like @ability.can? :edit, @post
). @ability.can? :edit, @post
)。 Second, your Ability
uses current_author
on both line 4 and 5, however you don't have a current_author
in your initialize
method. 其次,您的
Ability
在第4行和第5行都使用current_author
,但是您的initialize
方法中没有current_author
。 You have author
, though. 不过,您有
author
。 If no Author
object is available/given to the ability's initializer, you use a non-persisted author instead (and not a AuthorAbility, unless your AuthorAbility is what current_user
returns or initialize
in your ability gets as argument). 如果该功能的初始化程序没有可用的
Author
对象,则使用非持久性作者(而不是AuthorAbility,除非AuthorAbility是current_user
返回或在您的功能中进行initialize
东西作为参数)。 Something like this: 像这样:
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
Edit based on the comments to keep it simpler: 根据评论进行编辑以使其更简单:
Ideally you put a current_user
method inside your application controller and also make it available as helper in your views (because you may want to conditionally show/hide/change things in your view based on a logged-in user). 理想情况下,将
current_user
方法放入应用程序控制器中,并在视图中将其用作帮助程序(因为您可能希望基于登录的用户有条件地在视图中显示/隐藏/更改内容)。
class ApplicationController < ActionController::Base
helper_method :current_user
def current_user
# return the currently logged in user record
end
end
If this is new to you, I suggest to have a look at an authentication gem. 如果这对您来说是新手,我建议您看一下身份验证宝。 Devise also introduces this and authlogic describes this in its how-to and the example application.
Devise也对此进行了介绍,而authlogic在其使用方法和示例应用程序中对此进行了描述。 If you're doing authentication from scratch, you just need to return the user based on the session.
如果您要从头开始进行身份验证,则只需根据会话返回用户。
edit 2. You actually need to understand what you do, which IMHO is not the case at the moment. 编辑2.您实际上需要了解您的操作,恕我直言,目前情况并非如此。 You're doing a bit of a mess here ;-)
你在这里有点混乱;-)
Problem 1: current_user
needs to return the current author / user logged in (not an abilty nor fallback user nor something else) or nil
if no author is logged in. So you can eg do <% if current_user %>
in your view. 问题1:
current_user
需要返回当前登录的作者/用户 (不是abilty,fallback用户或其他身份),如果没有作者登录,则返回nil
。因此,例如,您可以在视图中执行<% if current_user %>
。 @current_ability ||= Author.new(current_author)
is plain wrong. @current_ability ||= Author.new(current_author)
是完全错误的。 The fallback from the ability class needs to stay in the ability class because cancan's methods can only be applied to an object and not to nil
. 来自能力类的后退需要保留在能力类中,因为cancan的方法只能应用于对象,而不能应用于
nil
。 So with author ||= Author.new
in your ability, you make sure that there is an object, even if no author is logged in (in which case current_author
returns nil
). 因此,如果您具有
author ||= Author.new
,即使没有作者登录,也请确保存在一个对象(在这种情况下, current_author
返回nil
)。
Problem 2: helper_method :current_author
actually does nothing because there is no current_author
method in your application controller. 问题2:
helper_method :current_author
实际上不执行任何操作,因为您的应用程序控制器中没有current_author
方法。 You need to somehow define current_author
. 您需要以某种方式定义
current_author
。
Problem 3: In your view, you're calling can?
问题3:在您看来,您在打电话
can?
on an instance of Author
which is wrong. 在一个
Author
实例上,这是错误的。 can?
is a method of Ability
. 是一种
Ability
的方法。 So you'd need to use @my_ability.can?
因此,您需要使用
@my_ability.can?
where @my_ability is an instance of eg Ability.new(Author.first)
. 其中@my_ability是例如
Ability.new(Author.first)
的实例。 This is used if you need to work with multiple abilities or customized something, which is not the case here, so just use can?
如果您需要使用多种能力或自定义某些内容,则使用此方法,此处不是这种情况,那么使用
can?
directly without a receiver (like @author.can?
). 直接没有接收者(例如
@author.can?
)。
For testing purposes, I'd create the following: 为了进行测试,我将创建以下内容:
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
So your current_user
returns a valid user (I hope, you need to at least have one in your database stored, though) and then can sort out the ability issues. 因此,您的
current_user
返回一个有效用户(不过,我希望您至少需要在数据库中存储一个用户),然后才能解决能力问题。 If your ability works, you implement your authentication. 如果您的能力有效,则可以实施身份验证。 As a beginner, I'd either stick to authlogic or devise .
作为一个初学者,我要么坚持authlogic要么设计一个 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.