Использование блоков для определения способностей в CanCan вызывает исключение - PullRequest
3 голосов
/ 24 августа 2010

Я использую камень CanCan Райана Бэйта для определения способностей, и некоторые базовые функции не работают. У меня есть модель Product и контроллер Products, где мое действие индекса выглядит так:

def index
    @req_host_w_port = request.host_with_port
    @products = Product.accessible_by(current_ability, :index)
end

Я получаю сообщение об ошибке, когда пытаюсь получить продукты методом accessible_by, я получаю эту ошибку:

Cannot determine SQL conditions or joins from block for :index Product(id: integer, secret: string, context_date: datetime, expiration_date: datetime, blurb: text, created_at: datetime, updated_at: datetime, owner_id: integer, product_type_id: integer, approved_at: datetime)

Мой класс способностей выглядит так:

can :index, Product do |product|
   product && !!product.approved_at
end

Это выглядит как очень простой пример, поэтому я удивлен, что он терпит неудачу, и мне интересно, пропускаю ли я что-то простое (то есть слишком долго смотрю на мой код).

Я немного больше исследовал и провел простой тест. Если вы посмотрите на приведенный ниже код, один пример работает нормально, а другой не получается, когда они должны делать то же самое.

# This works
can :index, Product, :approved_at => nil

# This fails
can :index, Product do |product|
    product && product.approved_at.nil?
end

Так что, похоже, проблема в том, как CanCan обрабатывает эти блоки. Я углубился в библиотеку и нашел, где возникла ошибка - в определении класса способностей CanCan:

def relevant_can_definitions_for_query(action, subject)
      relevant_can_definitions(action, subject).each do |can_definition|
        if can_definition.only_block?
          raise Error, "Cannot determine SQL conditions or joins from block for #{action.inspect} #{subject.inspect}"
        end
      end
    end

Итак, я проверил, что это за метод only_block?. Метод возвращает true, если в определении can есть блок, но нет условий, которые не имеют смысла для меня, потому что весь смысл блока состоит в том, чтобы определить условия внутри блока, когда они слишком сложны для следующего синтаксиса:

can :manage, [Account], :account_manager_id => user.id

Любое понимание этого вопроса было бы замечательно! Я также подал вопрос на странице CanCan GitHub, но я дошел до того, что мне, возможно, придется отказаться от библиотеки. Тем не менее, я понимаю, что многие люди успешно используют CanCan, и это такая базовая функциональность, я думаю, что я должен делать что-то не так. Тем более, что репозиторий git был обновлен 3 дня назад, и Райан Бейтс упоминает о поддержке Rails 3 в README.

Спасибо!

Ответы [ 3 ]

6 голосов
/ 24 августа 2010

Хорошо, поэтому я просмотрел вики и увидел, что accessible_by не будет работать при определении блоков. Кажется немного странным иметь это ограничение и не упоминать его в README, но, по крайней мере, я знаю, что это ограничение библиотеки, а не ошибка в моем или коде Райана Бейтса. Для тех, кто заинтересован, правильный способ определить мои способности выше выглядит следующим образом:

# will fail    
can :index, Product do |product|
   product && product.approved_at.nil?
end

# will pass
can :index, Product
cannot :index, Product, :approved_at => nil
3 голосов
/ 09 сентября 2011

Я также столкнулся с этой проблемой, когда иногда вы можете выразить способность / разрешение только через блок (код Ruby) и не можете выразить его как условие SQL или именованную область действия.

В качестве обходного пути, я просто делаю свой поиск, как обычно без CanCan, и затем фильтрую это значение, используя select!, чтобы содержать только подмножество записей, которые пользователь фактически имеет разрешение на просмотр.:

# Don't use accessible_by
@blog_posts = BlogPost.where(...)
@blog_posts.select! {|blog_post| can?(:read, blog_post)}

Или более обобщенно:

@objects = Object.all
@objects.select! {|_| can?(:read, _)}
0 голосов
/ 11 февраля 2011

Я подал заявку, чтобы добавить это к документации:

https://github.com/ryanb/cancan/issues/issue/276

...