在Ruby中实现枚举习语的最佳方法是什么?我正在寻找一些东西,我可以使用(几乎)像Java/ c#枚举。
当前回答
另一种使用一致的平等处理来模拟枚举的方法(无耻地采用了Dave Thomas)。允许打开枚举(很像符号)和关闭(预定义的)枚举。
class Enum
def self.new(values = nil)
enum = Class.new do
unless values
def self.const_missing(name)
const_set(name, new(name))
end
end
def initialize(name)
@enum_name = name
end
def to_s
"#{self.class}::#@enum_name"
end
end
if values
enum.instance_eval do
values.each { |e| const_set(e, enum.new(e)) }
end
end
enum
end
end
Genre = Enum.new %w(Gothic Metal) # creates closed enum
Architecture = Enum.new # creates open enum
Genre::Gothic == Genre::Gothic # => true
Genre::Gothic != Architecture::Gothic # => true
其他回答
如果您担心符号的拼写错误,请确保您的代码在访问具有不存在键的值时引发异常。你可以使用fetch而不是[]:
my_value = my_hash.fetch(:key)
或者在默认情况下,如果你提供了一个不存在的键,让哈希抛出一个异常:
my_hash = Hash.new do |hash, key|
raise "You tried to access using #{key.inspect} when the only keys we have are #{hash.keys.inspect}"
end
如果散列已经存在,你可以添加异常引发行为:
my_hash = Hash[[[1,2]]]
my_hash.default_proc = proc do |hash, key|
raise "You tried to access using #{key.inspect} when the only keys we have are #{hash.keys.inspect}"
end
通常情况下,您不必担心常量的拼写安全问题。如果你拼错了常量名,通常会引发异常。
irb(main):016:0> num=[1,2,3,4]
irb(main):017:0> alph=['a','b','c','d']
irb(main):018:0> l_enum=alph.to_enum
irb(main):019:0> s_enum=num.to_enum
irb(main):020:0> loop do
irb(main):021:1* puts "#{s_enum.next} - #{l_enum.next}"
irb(main):022:1> end
输出:
1 - a 2 - b 3 - c 4 - d
另一种使用一致的平等处理来模拟枚举的方法(无耻地采用了Dave Thomas)。允许打开枚举(很像符号)和关闭(预定义的)枚举。
class Enum
def self.new(values = nil)
enum = Class.new do
unless values
def self.const_missing(name)
const_set(name, new(name))
end
end
def initialize(name)
@enum_name = name
end
def to_s
"#{self.class}::#@enum_name"
end
end
if values
enum.instance_eval do
values.each { |e| const_set(e, enum.new(e)) }
end
end
enum
end
end
Genre = Enum.new %w(Gothic Metal) # creates closed enum
Architecture = Enum.new # creates open enum
Genre::Gothic == Genre::Gothic # => true
Genre::Gothic != Architecture::Gothic # => true
这似乎有点多余,但这是我使用过几次的方法,特别是在集成xml或类似的方法时。
#model
class Profession
def self.pro_enum
{:BAKER => 0,
:MANAGER => 1,
:FIREMAN => 2,
:DEV => 3,
:VAL => ["BAKER", "MANAGER", "FIREMAN", "DEV"]
}
end
end
Profession.pro_enum[:DEV] #=>3
Profession.pro_enum[:VAL][1] #=>MANAGER
这给了我c#枚举的严谨性,并且它与模型绑定。
这是我在Ruby中处理枚举的方法。我想要的是简短而甜蜜的,不一定是最像c的。任何想法吗?
module Kernel
def enum(values)
Module.new do |mod|
values.each_with_index{ |v,i| mod.const_set(v.to_s.capitalize, 2**i) }
def mod.inspect
"#{self.name} {#{self.constants.join(', ')}}"
end
end
end
end
States = enum %w(Draft Published Trashed)
=> States {Draft, Published, Trashed}
States::Draft
=> 1
States::Published
=> 2
States::Trashed
=> 4
States::Draft | States::Trashed
=> 5
推荐文章
- 从字符串中移除子字符串
- 如何从Ruby数组中创建平均值?
- 如何在ruby中做一个安全的连接路径名?
- Ruby中没有增量操作符(++)?
- 如何得到一个特定的输出迭代哈希在Ruby?
- Ruby正则表达式中\A \z和^ $的区别
- 我如何使一个enum可解码在Swift?
- 如何设置enum为空
- 选择Enum类型的默认值而无需更改值
- __FILE__在Ruby中是什么意思?
- Paperclip::Errors::MissingRequiredValidatorError with Rails
- 是否有一种方法来检查是否int是合法的enum在c# ?
- Ruby:如何将散列转换为HTTP参数?
- Java中枚举的命名:单数还是复数?
- 在ROR迁移期间,将列类型从Date更改为DateTime