在自定义创建操作中让Cancan的load_and_authorize_resource起作用

6
尝试在我的应用程序中设置Cancan,但我的PostsController出了问题。
简而言之,当创建Post时,我想将其与current_user关联起来,因此我的create操作看起来像这样:
class PostsController < ApplicationController
  before_filter :login_required, :except => [:index, :show]
  load_and_authorize_resource
  ...
  def create
    # @post = Post.new(params[:post])   # <-- covered by load_and_authorize_resource
    @user = current_user
    @post = @user.posts.create(params[:post])
    respond_to do |format|
    ...
  end
  ...
end

我不确定load_and_authorize_resource的目的是什么(除了显而易见的)。但在这种情况下呢?我是否需要以某种方式覆盖load_and_authorize_resource来创建操作?还是有另一种(更好的)方法来加载@user,然后再创建@post

3个回答

12

我认为最好的解决方案,由于这是一个独特的问题,你需要将load_and_authorize_resource行改成这样:

load_and_authorize_resource :except => [:create]

并且对于这个动作:

def create
  authorize! :create, Post
  current_user.posts.create(params[:post])
end

对我来说很有效。你也可以在:except后面加上:new。 - gfreezy

3
一个更简单的解决方案是使用嵌套资源,而不是创建自定义操作。
直接摘自CanCan Wiki: 嵌套资源

As of 1.4, it's also possible to nest through a method, this is commonly the current_user method.

 class ProjectsController < ApplicationController
   load_and_authorize_resource :through => :current_user
 end 

Here everything will be loaded through the current_user.projects association.

这样做也更安全,因为加载帖子将通过控制器中的其他操作的关联完成。

从控制器访问另一个用户的项目时出现错误怎么办?它会抛出错误 Couldn't find Project with 'id'=<another_user_project_id> [WHERE projects.user_id = ?] - Braham Shakti

0

这个解决方案对我也有效

authorize_resource class: 'User'


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接