我正在使用Rails 4.0.0,ruby 2.0.0p247和CanCan 1.6.10。
如何根据用户在联接表中的角色授权使用CanCan的用户(has_many:through)?
我有3个模型:User
,Group
和GroupUser
。
用户和组通过GroupUser表关联为has_many
。每个GroupUser还有一个role
字段,可以是“编辑者”或“所有者”。一个组可以有多个用户,每个用户具有不同的角色。此外,用户可以在多个组中拥有角色。
我的应用设置包含CanCan功能,但不是限制只有具有正确角色的用户访问,它授权所有人 。
模型的设置如下。另请注意,Group有一种返回其所有者列表的方法。
class User < ActiveRecord::Base
has_many :group_users
has_many :groups, through: :group_users
end
class Group < ActiveRecord::Base
has_many :group_users
has_many :users, through: :group_users
def owners
User.find(self.group_users.where(role: 'owner').map(&:user_id))
end
end
class GroupUser < ActiveRecord::Base
belongs_to :user
belongs_to :group
end
CanCan能力。请注意,它在群组中使用owners
方法。
class Ability
include CanCan::Ability
def initialize(user)
can :update, Group do |group|
group.owners.include?(user)
end
end
end
视图如下。在这里,无法看到链接的用户仍然可以看到它。
<ul class="groups">
<% @groups.each do |group| %>
<li>
<p><%= group.name %></p>
<% if can? :update, Group %>
<%= link_to "Edit", edit_group_path(group) %>
<% end %>
</li>
<% end %>
</ul>
最后,视图的控制器操作是:
def index
@groups = current_user.groups
end
。 。 。 一个有趣的事情是,即使它在实际使用中不起作用,也会通过以下单元测试:
test 'user can only update groups they own' do
ability_one = Ability.new(users(:one)) # Owner
ability_two = Ability.new(users(:two)) # Not-owner
assert ability_one.can?(:update, groups(:one))
assert ability_two.cannot?(:update, groups(:two))
end
答案 0 :(得分:3)
我认为你应该让cancan
在这里使用真实对象,将实际的group
对象传递给can?
方法而不是Group
类:
在视图中:
<% if can? :update, group %>
而不是:
<% if can? :update, Group %>
这样,如果cancan
能够current_user
实际的:update
,您会问group
。由于没有为通用Group
对象设置操作的能力,因此第二个条件将始终为真。