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

В моем новом проекте у меня есть ресурс Ставка, который другие пользователи могут читать только в том случае, если они являются владельцами ставки или его друзьями. Основная проблема возникает, когда я хочу определить возможности для действия index. В действии индекса блок не выполняется, поэтому я думаю, что это не вариант.

Проиллюстрируем это. Если бы я хотел, чтобы только владелец мог индексировать ставки, этого было бы достаточно:

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)


В вашей модели 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

person Amir Rubin    schedule 18.07.2012
comment
Это не работает. Условия в блоках способностей не используются в таких действиях, как index. - person Gawyn; 18.07.2012
comment
Вы правы, я не внимательно прочитал ваш вопрос :( Я дам еще одно предложение... - person Amir Rubin; 18.07.2012

Только сейчас я нашел решение, но оно мне не очень нравится. Речь идет о создании пользовательского действия и определении возможностей для него. Например...

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

def index
  authorize! :index_bets, @user
end

В способности.rb:

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

Это работает, но я не чувствую себя прекрасно, используя его. Неужели нет ничего более элегантного?

person Gawyn    schedule 18.07.2012