Ruby Comparable 实践
我们有一个 User 模型,此模型有一个 pack_status 属性, pack_status 主要用于控制用户的升级权值, 它有 4 个值: init, bronze, silver 和 gold, 其中 bronze 比 init 高级, silver 比 bronze 高级, gold 比 silver 高级。 我们经常需要对用户之间的 pack_status 进行比较,
user1.pack_status > user2.pack_status
user1.pack_status >= 'bronze'
如果按照字符串的形式去比较,我们会发现:
'silver' > 'init' > 'gold' > 'bronze'
这种顺序和我们的预期不相符, 这时候我们可以把 Comparable
请出来了,故名思义, Comparable
是用来构造可以进行比较的类。
我们首先创建一个叫 PackStatus 的类, 然后在此类里面加入 Comparable 模块,
class PackStatus
include Comparable
end
此时 PackStatus 还没有什么用处,按照 Comparable 的定义,我们需要实现 <=>
方法,
class PackStatus
include Comparable
attr_reader :name
STATUS = %w(init bronze silver gold)
InvalidStatus = Class.new(StandardError)
def initialize name
raise InvalidStatus if !STATUS.include?(name)
@name = name
end
def <=> other_status
if other_status.is_a? String
STATUS.index(name) <=> STATUS.index(other_status)
else
STATUS.index(name) <=> STATUS.index(other_status.name)
end
end
end
我们可以对其进行测试,
assert PackStatus.new('init') < PackStatus.new('bronze')
assert PackStatus.new('init') < 'bronze'
assert_equal PackStatus.new('init'), 'init'
assert PackStatus.new('bronze') < PackStatus.new('silver')
assert PackStatus.new('bronze') < 'silver'
assert_equal PackStatus.new('bronze'), 'bronze'
assert PackStatus.new('silver') < PackStatus.new('gold')
assert PackStatus.new('silver') < 'gold'
assert_equal PackStatus.new('silver'), 'silver'