0

我有一个带有序列化哈希的 UserProfile 模型,它定义了各种隐私选项:

class UserProfile < ActiveRecord::Base
  attr_accessible :bio, :first_name, :last_name, :location, :website_url, :vanity_url, :avatar
  belongs_to :user
  has_one :avatar
  before_create :default_privacy

  PRIVACY_SETTINGS = [:public, :app_global, :contacts, :private]
  serialize :privacy_options, Hash

  private

  def default_privacy
    return if self.privacy_options
    self.privacy_options = {:personal => :app_global, :contacts => :app_global, :productions => :app_global}
  end

end

我正在使用 CanCan 授权访问用户配置文件,如下所示:

class Ability
  include CanCan::Ability

  def initialize(user)
    user ||= User.new # guest user (not logged in)
    can :create, UserProfile
    can :read, UserProfile, :privacy_options[:personal].eql?(:public)
    if user.role? :user
      can :read, UserProfile, privacy_options[:personal].eql?(:cp_global)
      can :update, UserProfile, :user_id => user.id
    end
  end

end

但是,以下单元测试会产生test_user_can_only_read_profile_with_personal_scope_set_to_public(AbilityTest): TypeError: can't convert Symbol into Integer

require 'test_helper'

class AbilityTest < ActiveSupport::TestCase

  def setup
    @up = user_profiles(:joes_user_profile)
    @ability = Ability.new(@user)
  end

  test "user can only read profile with personal scope set to public" do
    assert @ability.can?(:read, @up)
    @up.personal_privacy = :private
    @up.save
    refute @ability.can?(:read, @up)
  end
end

我对 Ruby 和 Rails 很陌生。在能力模型中测试 privacy_options 键值的正确方法是什么?

4

1 回答 1

2

替换这个:

can :read, UserProfile, :privacy_options[:personal].eql?(:public)

有了这个 :

can :read, UserProfile do |profile| 
  profile.privacy_options[:personal] == :public 
end

问题是:

  • :privacy_options[:personal]是符号的无效语法
  • CanCan 需要选项哈希或块作为方法的(可选)参数(有关更多信息,can请参阅使用块定义能力)

作为旁注,如果可能的话,您不应该将您的隐私选项序列化为哈希 - 正如 Cancan 的文档所述,仅在加载实际记录时才使用块条件。如果您希望能够对集合设置授权,则需要一个哈希条件(可以转换为关系),这反过来又要求您的条件以属性为目标(或至少可以通过 SQL 查询表达的东西)

于 2013-04-23T14:31:25.297 回答