我有一个带有序列化哈希的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的新手。在Ability模型中测试privacy_options键值的正确方法是什么?
答案 0 :(得分:2)
替换这个:
can :read, UserProfile, :privacy_options[:personal].eql?(:public)
用这个:
can :read, UserProfile do |profile|
profile.privacy_options[:personal] == :public
end
问题在于:
:privacy_options[:personal]
是符号can
方法的(optionnal)参数(有关详细信息,请参阅Defining abilities with blocks)作为附注,如果可能,您不应将隐私选项序列化为哈希 - 正如Cancan的文档所述,块条件仅在加载实际记录时使用。如果您希望能够在集合上设置授权,则需要哈希条件(可以转换为relation),这又需要您的条件来定位属性(或者至少可以表达的内容)通过SQL查询)