Was ist der beste Weg, um die enum Idiom in Ruby zu implementieren? Ich bin auf der Suche nach etwas, das ich (fast) wie die Java/C# enums verwenden können.
Antworten
Zu viele Anzeigen?Sehen Sie sich das Rubin-Emaille an, https://github.com/dblock/ruby-enum .
class Gender
include Enum
Gender.define :MALE, "male"
Gender.define :FEMALE, "female"
end
Gender.all
Gender::MALE
Ich weiß, es ist schon lange her, dass der Mann diese Frage gestellt hat, aber ich hatte dieselbe Frage und dieser Beitrag hat mir keine Antwort gegeben. Ich wollte eine einfache Möglichkeit, um zu sehen, was die Zahl darstellt, einfachen Vergleich, und vor allem ActiveRecord Unterstützung für Lookup mit der Spalte, die die Enum.
Da ich nichts gefunden habe, habe ich eine geniale Implementierung namens yinum die alles erlaubte, was ich suchte. Made Tonne von Spezifikationen, so bin ich ziemlich sicher, dass es sicher ist.
Einige Beispielfunktionen:
COLORS = Enum.new(:COLORS, :red => 1, :green => 2, :blue => 3)
=> COLORS(:red => 1, :green => 2, :blue => 3)
COLORS.red == 1 && COLORS.red == :red
=> true
class Car < ActiveRecord::Base
attr_enum :color, :COLORS, :red => 1, :black => 2
end
car = Car.new
car.color = :red / "red" / 1 / "1"
car.color
=> Car::COLORS.red
car.color.black?
=> false
Car.red.to_sql
=> "SELECT `cars`.* FROM `cars` WHERE `cars`.`color` = 1"
Car.last.red?
=> true
Dies ist mein Ansatz für Enums in Ruby. Ich wollte kurz und bündig sein, nicht unbedingt das C-ähnlichste. Irgendwelche Ideen?
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
Der beste leichtgewichtige Ansatz wäre vielleicht
module MyConstants
ABC = Class.new
DEF = Class.new
GHI = Class.new
end
Auf diese Weise haben Werte zugehörige Namen, wie in Java/C#:
MyConstants::ABC
=> MyConstants::ABC
Um alle Werte zu erhalten, können Sie Folgendes tun
MyConstants.constants
=> [:ABC, :DEF, :GHI]
Wenn Sie den Ordinalwert einer Aufzählung benötigen, können Sie Folgendes tun
MyConstants.constants.index :GHI
=> 2
Wenn Sie sich Sorgen um Tippfehler bei Symbolen machen, stellen Sie sicher, dass Ihr Code eine Ausnahme auslöst, wenn Sie auf einen Wert mit einem nicht existierenden Schlüssel zugreifen. Sie können dies tun, indem Sie fetch
statt []
:
my_value = my_hash.fetch(:key)
oder indem der Hash standardmäßig eine Ausnahme auslöst, wenn Sie einen nicht existierenden Schlüssel angeben:
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
Wenn der Hash bereits vorhanden ist, können Sie ein Verhalten, das Ausnahmen auslöst, hinzufügen:
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
Normalerweise müssen Sie sich bei Konstanten keine Gedanken über die Sicherheit von Tippfehlern machen. Wenn Sie einen Konstantennamen falsch schreiben, wird normalerweise eine Ausnahme ausgelöst.