如何将cancan的祖先关系默认为树的内部节点?

Joh*_*gle 5 cancan ruby-on-rails-3

我正在使用cancan来授权我的控制器操作.其中一个由cancan授权访问的类是一个树,使用acts_as_ancestry实现.我在使用load_and_authorize_resource不允许用户访问根级别时遇到问题,而是允许从内部节点开始访问.

以下是一些相关类定义:

class User < ActiveRecord::Base
  belongs_to :organization, :inverse_of => :users
end

class Post < ActiveRecord::Base
  belongs_to :organization, :inverse_of => :posts
end

class Organization < ActiveRecord::Base
  has_ancestry :cache_depth => true
  has_many :users, :inverse_of => :organization
  has_many :posts, :inverse_of => :organization
end
Run Code Online (Sandbox Code Playgroud)

管理帖子的规则是"您可以管理您下面任何组织中的帖子".我的康康技能定义是这样的:

class Ability
  include CanCan::Ability

  def initialize(user)
    user ||= User.new 

    # subtree_ids is added by acts_as_ancestry
    can :manage, Post, {:organization_id => user.organization.subtree_ids}
  end
end
Run Code Online (Sandbox Code Playgroud)

在控制器中,我有这个(省略其他操作)

class PostsController < ApplicationController
  load_and_authorize_resource :post

  def index
  end

  def new
  end
end
Run Code Online (Sandbox Code Playgroud)

当授权用户属于根组织时,一切正常.但是,当我以在内部节点上授权的用户身份登录时,索引操作正常,但是当调用新操作时,我收到can-can授权错误.

这是我在日志中看到的内容:

Access denied on new #<Post id: nil, organization_id: 1>
Run Code Online (Sandbox Code Playgroud)

organization_id 1(根)从架构来:

create_table "posts", :force => true do |t|
  t.integer  "organization_id", :default => 1
end
Run Code Online (Sandbox Code Playgroud)

使用cancan,新操作将构建一个新的Post并将其分配给@post.当它执行此操作时,它将使用从canAbilities.rb中的定义中获取的值初始化所有属性.但是,如果这些属性是数组,散列或范围,它将不会执行任何操作,并且默认值最终来自模式.

如何授权用户管理其子树中的帖子,但是当他们创建新帖子时,将其默认为其组织?

Rob*_*Rob 3

在cancan中,如果@post变量已经被你初始化,它不会调用它的load_resource,只做授权部分。请参阅文档的这一部分:https://github.com/ryanb/cancan/wiki/Authorizing-controller-actions,“覆盖加载”。

因此,最简单的解决方案是自己控制初始化并使其满足您的需要,如下所示:

class PostsController < ApplicationController
  before_filter :initialize_post, :only => [:new, :create]

  def initialize_post
    @post = current_user.organization.posts.build(params[:post]||{:name=>'Smashing Kittens'})
  end

  load_and_authorize_resource :post
  def index
  end

  def new
  end

  def create
  end
end
Run Code Online (Sandbox Code Playgroud)

您可以看到它在我根据您的帖子创建的测试项目中工作: https: //github.com/robmathews/cancan_test