Quelle est la meilleure façon de mettre en œuvre l’idiome enum en Ruby ? Je suis à la recherche de quelque chose que je peux utiliser (presque) comme le Java / C# enums.
Réponses
Trop de publicités?Deux façons. Symboles ( notation) ou constantes (
notation).
Les symboles sont appropriés lorsque vous voulez améliorer la lisibilité sans code d’ordures avec les chaînes littérales.
Les constantes sont appropriés lorsque vous avez une valeur sous-jacente qui est importante. Simplement déclarer un module pour contenir vos constantes et ensuite déclarer les constantes au sein de qui.
Je suis surpris que personne n'a offert quelque chose comme ce qui suit (récoltées à partir de la RAPI gem):
class Enum
private
def self.enum_attr(name, num)
name = name.to_s
define_method(name + '?') do
@attrs & num != 0
end
define_method(name + '=') do |set|
if set
@attrs |= num
else
@attrs &= ~num
end
end
end
public
def initialize(attrs = 0)
@attrs = attrs
end
def to_i
@attrs
end
end
Qui peut être utilisé comme:
class FileAttributes < Enum
enum_attr :readonly, 0x0001
enum_attr :hidden, 0x0002
enum_attr :system, 0x0004
enum_attr :directory, 0x0010
enum_attr :archive, 0x0020
enum_attr :in_rom, 0x0040
enum_attr :normal, 0x0080
enum_attr :temporary, 0x0100
enum_attr :sparse, 0x0200
enum_attr :reparse_point, 0x0400
enum_attr :compressed, 0x0800
enum_attr :rom_module, 0x2000
end
Exemple:
>> example = FileAttributes.new(3)
=> #<FileAttributes:0x629d90 @attrs=3>
>> example.readonly?
=> true
>> example.hidden?
=> true
>> example.system?
=> false
>> example.system = true
=> true
>> example.system?
=> true
>> example.to_i
=> 7
Ce qui est bien dans la base de données de scénarios, ou lorsque vous traitez avec style C des constantes/énumérations (comme c'est le cas lors de l'utilisation de FFI, qui RAPI fait un usage intensif de).
Aussi, vous n'avez pas à vous soucier des fautes de frappe provoquant le silence des échecs, comme vous le feriez avec l'aide d'un hachage de type de solution.
I l'utilisation de cette approche:
MyEnum = [MyValue1 = 'value1', MyValue2 = 'value2']
Je l'aime pour les avantages suivants:
- Il regroupe des valeurs visuellement comme un ensemble de
- Il fait un peu de compilation-le temps de vérifier (en contraste avec juste l'aide de symboles)
- Je peux facilement accéder à la liste de toutes les valeurs possibles: juste
MyEnum
- Je peux facilement accéder à des valeurs distinctes:
MyValue1
- Il peut être la valeur de tout temps, pas seulement Symbole
Les symboles peuvent me cause plus vous n'avez pas à écrire le nom de l'extérieur de la classe, si vous l'utilisez dans une autre classe (MyClass::MyValue1)
Pour ce faire, la plus idiomatique consiste à utiliser des symboles. Par exemple, au lieu de :
.. .vous pouvez simplement utiliser des symboles :
C’est un peu plus ouverte que les enums, mais il correspond bien à l’esprit de Ruby.
Symboles effectuent aussi très bien. En comparant les deux symboles pour l’égalité, par exemple, est beaucoup plus rapide que la comparaison de deux chaînes.
Je sais que ça a été un long temps depuis que le gars a posté cette question, mais j'ai eu la même question, et ce post ne m'a pas donné la réponse. Je voulais un moyen facile de voir ce que ce nombre représente, en faciliter la comparaison, et la plupart de tous les ActiveRecord de soutien pour la recherche de l'aide de la colonne représentant la enum.
Je n'ai rien trouvé, j'ai donc fait une impressionnante mise en œuvre appelée yinum qui a permis tout ce que je cherchais. Faites tonne de specs, donc je suis assez sûr qu'il est sécuritaire. Profitez-en!