在Ruby中实现枚举习语的最佳方法是什么?我正在寻找一些东西,我可以使用(几乎)像Java/ c#枚举。


当前回答

符号是红宝石之道。然而,有时我们需要与一些C代码或Java进行对话,这些代码或Java会为各种事情公开一些枚举。


#server_roles.rb
module EnumLike

  def EnumLike.server_role
    server_Symb=[ :SERVER_CLOUD, :SERVER_DESKTOP, :SERVER_WORKSTATION]
    server_Enum=Hash.new
    i=0
    server_Symb.each{ |e| server_Enum[e]=i; i +=1}
    return server_Symb,server_Enum
  end

end

然后可以这样使用


require 'server_roles'

sSymb, sEnum =EnumLike.server_role()

foreignvec[sEnum[:SERVER_WORKSTATION]]=8

这当然可以是抽象的,你可以滚动我们自己的Enum类

其他回答

如果你使用的是Rails 4.2或更高版本,你可以使用Rails枚举。

Rails现在默认有枚举,不需要包含任何宝石。

这与Java、c++的枚举非常相似(并且具有更多的特性)。

引用自http://edgeapi.rubyonrails.org/classes/ActiveRecord/Enum.html:

class Conversation < ActiveRecord::Base
  enum status: [ :active, :archived ]
end

# conversation.update! status: 0
conversation.active!
conversation.active? # => true
conversation.status  # => "active"

# conversation.update! status: 1
conversation.archived!
conversation.archived? # => true
conversation.status    # => "archived"

# conversation.update! status: 1
conversation.status = "archived"

# conversation.update! status: nil
conversation.status = nil
conversation.status.nil? # => true
conversation.status      # => nil

我实现过这样的枚举

module EnumType

  def self.find_by_id id
    if id.instance_of? String
      id = id.to_i
    end 
    values.each do |type|
      if id == type.id
        return type
      end
    end
    nil
  end

  def self.values
    [@ENUM_1, @ENUM_2] 
  end

  class Enum
    attr_reader :id, :label

    def initialize id, label
      @id = id
      @label = label
    end
  end

  @ENUM_1 = Enum.new(1, "first")
  @ENUM_2 = Enum.new(2, "second")

end

然后很容易做操作

EnumType.ENUM_1.label

...

enum = EnumType.find_by_id 1

...

valueArray = EnumType.values

查看ruby-enum gem, https://github.com/dblock/ruby-enum。

class Gender
  include Enum

  Gender.define :MALE, "male"
  Gender.define :FEMALE, "female"
end

Gender.all
Gender::MALE

符号是红宝石之道。然而,有时我们需要与一些C代码或Java进行对话,这些代码或Java会为各种事情公开一些枚举。


#server_roles.rb
module EnumLike

  def EnumLike.server_role
    server_Symb=[ :SERVER_CLOUD, :SERVER_DESKTOP, :SERVER_WORKSTATION]
    server_Enum=Hash.new
    i=0
    server_Symb.each{ |e| server_Enum[e]=i; i +=1}
    return server_Symb,server_Enum
  end

end

然后可以这样使用


require 'server_roles'

sSymb, sEnum =EnumLike.server_role()

foreignvec[sEnum[:SERVER_WORKSTATION]]=8

这当然可以是抽象的,你可以滚动我们自己的Enum类

最常用的方法是使用符号。例如,不要:

enum {
  FOO,
  BAR,
  BAZ
}

myFunc(FOO);

...你可以使用符号:

# You don't actually need to declare these, of course--this is
# just to show you what symbols look like.
:foo
:bar
:baz

my_func(:foo)

这比枚举更开放一些,但它很适合Ruby精神。

符号的表现也很好。例如,比较两个相等的符号要比比较两个字符串快得多。