CanCan, вложени ресурси и използване на методи

В моя нов проект имам ресурс Bet, който другите потребители могат да четат само ако са собственици на залога или негови приятели. Основният проблем идва, когато искам да дефинирам способности за действието на индекса. При действие с индекс блокът не се изпълнява, така че предполагам, че това не е опция.

Нека го илюстрираме. Ако исках само собственикът да може да индексира залозите, това щеше да е достатъчно:

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

Но имам нужда приемливите идентификатори да бъдат диапазон, определен от всички приятели на потребителя. Нещо като:

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

Но това не е правилният синтаксис на CanCan.

Предполагам, че много хора са имали проблеми с CanCan и вложени ресурси, но все още не съм видял отговор на това.


person Gawyn    schedule 18.07.2012    source източник


Отговори (2)


Във вашия модел за залагане създайте метод:

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

person Amir Rubin    schedule 18.07.2012
comment
Не работи. Условията в блокове за способности не се използват в действия като индекс. - person Gawyn; 18.07.2012
comment
Прав си, не прочетох внимателно въпроса ти :( Ще дам още едно предложение... - person Amir Rubin; 18.07.2012

Сега намерих решение, но не ми харесва много. Става въпрос за създаване на персонализирано действие и дефиниране на способности за него. Например...

В контролера:

def index
  authorize! :index_bets, @user
end

В ability.rb:

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

Работи, но не се чувствам добре да го използвам. Няма ли нещо по-елегантно?

person Gawyn    schedule 18.07.2012