1

在我的新项目中,我有一个资源 Bet,其他用户只有当他们是该赌注的所有者或他的朋友时才能阅读该资源。当我想为索引操作定义能力时,主要问题就出现了。在索引操作中,该块不会被执行,所以我想这不是一个选项。

让我们来说明一下。如果我只希望所有者能够为投注编制索引,这就足够了:

can :read, Bet, :user => { :id => user.id }

但我需要可接受的 id 是一个范围,由用户的所有朋友定义。就像是:

if (bet.user == user) || (bet.user.friends.include? user)
    can :read, Bet
end

但这不是正确的 CanCan 语法。

我想很多人都遇到过 CanCan 和嵌套资源的问题,但我仍然没有看到任何答案。

4

2 回答 2

1

在您的 Bet 模型中,创建一个方法:

def is_accessible_by? (user)
    owner = self.user
    owner == user || owner.friends.include?(user)
end

现在在ability.rb 中,设置您的 CanCan 权限:

can :read, Bet { |bet| bet.is_accessible_by?(user) }

编辑

正如您所指出的,由于索引操作没有对象的实例,因此上面的块不会被执行。

但是,听起来您正在尝试做的事情 - 列出用户或其朋友拥有的投注 - 不应该使用 CanCan 或权限来处理。我会在我的用户模型中创建一个函数:

def bet_listings
    friend_bets = friends.inject([]){ |bets, friend| bets<<friend.bets; bets }
    self.bets + friend_bets
end

然后在您的索引操作中: @bets = user.bet_listings

于 2012-07-18T14:13:03.257 回答
0

刚才我找到了一个解决方案,但我不太喜欢它。它是关于创建自定义操作并为其定义能力。例如...

在控制器中:

def index
  authorize! :index_bets, @user
end

在能力.rb 中:

can :index_bets, User do |friend|
  user == friend || user.friends.include?(friend)
end

它有效,但我对使用它感觉不太好。没有更优雅的吗?

于 2012-07-18T14:02:57.050 回答