3

我使用的是Rails 4.0.0,ruby 2.0.0p247和CanCan 1.6.10。使用CanCan基於連接表中的一個角色爲Rails 4授權用戶

我如何根據CanCan在連接表(has_many:through)中的角色授權用戶?

我有3個機型:User,GroupGroupUser

用戶和組通過GroupUser表關聯爲has_many。每個GroupUser還有一個role字段,可以是「編輯」或「所有者」。一個組可以有多個用戶,每個用戶都有不同的角色。另外,用戶可以在多個組中具有角色。

我有應用程序的設置與慘慘的能力,但不是限制只能訪問用戶提供了正確的角色,它授權大家

型號設置如下。另外,請注意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能力。請注意,它在Group上使用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 

回答

2

我想你應該讓cancan工作與真實物體在這裏,通過實際group對象到can?方法,而不是Group類:

在視圖:

<% if can? :update, group %> 

代替:

<% if can? :update, Group %> 

這樣你會問,如果cancancurrent_user能夠:update實際group。由於沒有爲通用對象操作設置能力,第二個條件將始終爲真。

+1

哇,那很容易。我花了很多時間在cancan文檔上查看[檢查功能wiki](https://github.com/ryanb/cancan/wiki/Checking-Abilities),但仍錯過了這一點:「重要提示:如果塊或散列的條件存在時,它們將在檢查課程時被忽略,並且將返回true「。感謝您的回答。 – ahuth