Как я могу разрешить пользователю обновлять только отзывы, написанные им с использованием cancan?

#ruby-on-rails #cancan

#ruby-on-rails #cancan

Вопрос:

Я просматривал railscast Райана Бейтса об использовании cancan, но я в замешательстве относительно того, почему проверка того, написал ли пользователь отзыв, а затем разрешение им редактировать его, если они есть, у меня не работает.

вот код, который у меня есть:

 class Ability
  include CanCan::Ability

  def initialize(user)
    user ||= User.new # guest user (not logged in)
    if user.role == "admin"
      can :manage, :all
    else
      can :read, :all
      if user.role == "author"
        can :create, Review
        can :update, Review do |review|
          review.try(:user) == user
        end
      end
    end
  end
end
  

Я хочу, чтобы авторы могли обновлять только те обзоры, которые они написали, все остальные возможности работают нормально, но в тот момент, когда автор может обновлять отзывы, написанные всеми, чего мне здесь не хватает?

Я использую возможность решать, отображать или нет ссылку на редактирование в частичном обзоре:

   <% if can? :update, Review %>
    testing
  <% end %>
  

Спасибо за любую помощь!

Ответ №1:

На ваш взгляд, вам следует написать что-то вроде

 <% if can? :update, @review %>
  testing
<% end %>
  

Поэтому передайте фактический объект обзора, а не просто класс.

Комментарии:

1. спасибо за ответ, это все еще не сработало с использованием ‘@review’, но использование ‘review’ работает.

Ответ №2:

Попробуйте:

 review.user_id == user.id
  

Вместо:

 review.try(:user) == user
  

Вы сравниваете два разных экземпляра одного и того же пользователя. Вероятно, для сравнения используется user.object_id. Rails 3.1 исправляет это, используя карту идентификации для ActiveRecord.

Для подтверждения:

 user.find(1) == user.find(1)
  

Ответ №3:

Я бы не стал использовать блок для этого варианта использования и вместо этого использовал подход CanCan с использованием хеширования атрибутов:

 if user.role == "author"
  can :create, Review
  can :update, Review, :user_id => user.id
end
  

Это будет сравниваться на основе идентификатора пользователя, а не самого пользовательского объекта.