Как реализовать Enums в Ruby? - PullRequest
       87

Как реализовать Enums в Ruby?

301 голосов
/ 16 сентября 2008

Какой лучший способ реализовать идиому enum в Ruby? Я ищу что-то, что я могу использовать (почти), например перечисления Java / C #.

Ответы [ 26 ]

4 голосов
/ 04 марта 2009

Кто-то пошел дальше и написал рубиновый камень под названием Renum . Он утверждает, что получил наиболее близкое поведение в стиле Java / C #. Лично я все еще изучаю Ruby, и я был немного шокирован, когда мне хотелось, чтобы конкретный класс содержал статическое перечисление, возможно, хеш, который не совсем легко найти через Google.

3 голосов
/ 28 декабря 2015

Недавно мы выпустили гем , который реализует Enums in Ruby . В моем посте вы найдете ответы на свои вопросы. Также я описал, почему наша реализация лучше существующих (на самом деле, в Ruby есть много реализаций этой функции, хотя и в виде гемов).

3 голосов
/ 17 сентября 2008

Все зависит от того, как вы используете перечисления Java или C #. То, как вы его используете, будет определять решение, которое вы выберете в Ruby.

Попробуйте собственный тип Set, например:

>> enum = Set['a', 'b', 'c']
=> #<Set: {"a", "b", "c"}>
>> enum.member? "b"
=> true
>> enum.member? "d"
=> false
>> enum.add? "b"
=> nil
>> enum.add? "d"
=> #<Set: {"a", "b", "c", "d"}>
2 голосов
/ 28 февраля 2012

Я реализовал перечисления вот так

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
2 голосов
/ 14 июля 2017

Другое решение - использование OpenStruct. Это довольно прямо и чисто.

https://ruby -doc.org / STDLIB-2.3.1 / libdoc / ostruct / RDoc / OpenStruct.html

Пример:

# bar.rb
require 'ostruct' # not needed when using Rails

# by patching Array you have a simple way of creating a ENUM-style
class Array
   def to_enum(base=0)
      OpenStruct.new(map.with_index(base).to_h)
   end
end

class Bar

    MY_ENUM = OpenStruct.new(ONE: 1, TWO: 2, THREE: 3)
    MY_ENUM2 = %w[ONE TWO THREE].to_enum

    def use_enum (value)
        case value
        when MY_ENUM.ONE
            puts "Hello, this is ENUM 1"
        when MY_ENUM.TWO
            puts "Hello, this is ENUM 2"
        when MY_ENUM.THREE
            puts "Hello, this is ENUM 3"
        else
            puts "#{value} not found in ENUM"
        end
    end

end

# usage
foo = Bar.new    
foo.use_enum 1
foo.use_enum 2
foo.use_enum 9


# put this code in a file 'bar.rb', start IRB and type: load 'bar.rb'
2 голосов
/ 03 октября 2008

Символы - это рубиновый путь. Тем не менее, иногда нужно поговорить с каким-нибудь кодом на C или чем-то или с 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

2 голосов
/ 17 апреля 2013

Это кажется немного излишним, но эту методологию я использовал несколько раз, особенно когда я интегрируюсь с 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 #, и оно привязано к модели.

1 голос
/ 06 марта 2012
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 -
2 - б
3 - с
4 - д

1 голос
/ 11 июля 2012
module Status
  BAD  = 13
  GOOD = 24

  def self.to_str(status)
    for sym in self.constants
      if self.const_get(sym) == status
        return sym.to_s
      end
    end
  end

end


mystatus = Status::GOOD

puts Status::to_str(mystatus)

Выход:

GOOD
1 голос
/ 16 сентября 2008

Большинство людей используют символы (это синтаксис :foo_bar). Это своего рода уникальные непрозрачные значения. Символы не принадлежат ни к какому типу enum-стиля, поэтому они на самом деле не являются точным представлением типа enum в C, но это в значительной степени так же хорошо, как и получается.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...