Quelle est la meilleure façon d'implémenter l'idiome enum dans Ruby? Je cherche quelque chose que je peux utiliser (presque) comme les énumérations Java / C #.
@auramo, bonne question et excellent choix pour la meilleure réponse. Aimez-le ou détestez-le, vous n'obtenez aucune sécurité de type et (au moins dans Ruby) aucune sécurité de faute de frappe. J'ai été ravi lorsque j'ai découvert des énumérations en C # et plus tard en Java (choisissez une valeur, mais à partir de celles-ci!), Ruby ne fournit en aucun cas un véritable moyen de le faire.
Dan Rosenstark
2
Le problème avec cette question est que les énumérations Java et C # sont des choses radicalement différentes. Un membre de l'énumération Java est une instance d'objet et un singleton. Une énumération Java peut avoir un constructeur. En revanche, les énumérations C # sont basées sur des valeurs primitives. Quel comportement le questionneur recherche-t-il? Bien qu'il soit probable que le cas C # soit recherché, Java est explicitement mentionné, plutôt que C ou C ++, il y a donc un doute. Quant à suggérer qu'il n'y a aucun moyen d'être «sûr» dans Ruby, c'est complètement faux, mais vous devez implémenter quelque chose de plus sophistiqué.
user1164178
Réponses:
319
Deux manières. Symboles ( :foonotation) ou constantes ( FOOnotation).
Les symboles sont appropriés lorsque vous souhaitez améliorer la lisibilité sans encombrer le code avec des chaînes littérales.
Les constantes sont appropriées lorsque vous avez une valeur sous-jacente qui est importante. Déclarez simplement un module pour contenir vos constantes, puis déclarez les constantes à l'intérieur.
moduleFoo
BAR =1
BAZ =2
BIZ =4end
flags =Foo::BAR |Foo::BAZ # flags = 3
Que faire si ces énumérations sont également stockées dans la base de données? La notation des symboles fonctionne-t-elle? Je doute ...
Phương Nguyễn
J'utiliserais l'approche des constantes si je sauvegardais dans une base de données. Bien sûr, vous devez alors faire une sorte de recherche lorsque vous retirez les données de la base de données. Vous pouvez également utiliser quelque chose comme :minnesota.to_slors de l'enregistrement dans une base de données pour enregistrer la version chaîne du symbole. Rails, je crois, a des méthodes d'aide pour gérer certains de ces problèmes.
mlibby
7
Un module ne serait-il pas préférable de regrouper des constantes - car vous n'en ferez aucune instance?
thomthom
3
Juste un commentaire. Ruby est un peu pénible à propos des conventions de dénomination, mais pas vraiment évidentes à leur sujet jusqu'à ce que vous les survoliez. Les noms des énumérations doivent être en majuscules et la première lettre du nom du module doit être en majuscule pour que ruby sache que le module est un module de constantes.
Rokujolady
3
Pas tout à fait vrai. La première lettre de la constante doit être en majuscule, mais pas toutes les lettres. C'est une question de préférence conventionnelle. Par exemple, tous les noms de module et les noms de classe sont également des constantes.
Michael Brown
59
Je suis surpris que personne n'ait offert quelque chose comme ce qui suit (récolté à partir de la gemme RAPI ):
classEnum
privatedefself.enum_attr(name, num)
name = name.to_s
define_method(name +'?')do@attrs& num !=0end
define_method(name +'=')do|set|if set@attrs|= numelse@attrs&=~numendendend
publicdef initialize(attrs =0)@attrs= attrsenddef to_i@attrsendend
Cela fonctionne bien dans les scénarios de base de données, ou lorsqu'il s'agit de constantes / énumérations de style C (comme c'est le cas lors de l'utilisation de FFI , que RAPI utilise largement).
De plus, vous n'avez pas à vous soucier des fautes de frappe provoquant des échecs silencieux, comme vous le feriez avec une solution de type hachage.
C'est un excellent moyen de résoudre ce problème particulier, mais la raison pour laquelle personne n'a suggéré que cela a probablement à voir avec le fait qu'il ne ressemble pas beaucoup aux énumérations C # / Java.
mlibby
1
Ceci est un peu incomplet, mais sert de bon indice sur la façon dont vous pouvez implémenter des solutions avec une approche dynamique. Cela ressemble à une énumération C # avec l'ensemble FlagsAttribute, mais comme les solutions basées sur les symboles / constantes ci-dessus, c'est une réponse parmi tant d'autres. Le problème est la question d'origine, qui est confuse dans son intention (C # et Java ne sont pas interchangeables). Il existe de nombreuses façons de détailler des objets dans Ruby; sélectionner le bon dépend du problème à résoudre. Répliquer servilement les fonctionnalités dont vous n'avez pas besoin est erroné. La bonne réponse doit dépendre du contexte.
user1164178
52
La façon la plus idiomatique de le faire est d'utiliser des symboles. Par exemple, au lieu de:
enum {
FOO,
BAR,
BAZ}
myFunc(FOO);
... vous pouvez simplement utiliser des symboles:
# 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)
C'est un peu plus ouvert que les énumérations, mais cela correspond bien à l'esprit Ruby.
Les symboles fonctionnent également très bien. La comparaison de deux symboles pour l'égalité, par exemple, est beaucoup plus rapide que la comparaison de deux chaînes.
Les frameworks Ruby populaires reposent fortement sur la métaprogrammation d'exécution, et effectuer trop de vérification du temps de chargement enlèverait la plupart de la puissance expressive de Ruby. Pour éviter les problèmes, la plupart des programmeurs Ruby pratiquent la conception pilotée par les tests, qui détectera non seulement les fautes de frappe, mais également les erreurs logiques.
emk
10
@yar: Eh bien, la conception du langage est une série de compromis et les fonctionnalités du langage interagissent. Si vous voulez une bonne langue très dynamique, allez avec Ruby, écrivez d'abord vos tests unitaires et allez avec l'esprit de la langue. :-) Si ce n'est pas ce que vous recherchez, il existe des dizaines d'autres excellentes langues, chacune faisant des compromis différents.
emk
10
@emk, je suis d'accord, mais mon problème personnel est que je me sens assez à l'aise dans Ruby, mais je ne me sens pas à l'aise dans la refactorisation dans Ruby. Et maintenant que j'ai commencé à écrire des tests unitaires (enfin), je me rends compte qu'ils ne sont pas une panacée: je suppose que 1) que le code Ruby n'est pas massivement refactorisé souvent, en pratique et 2) Ruby n'est pas la fin -de la ligne en termes de langages dynamiques, précisément parce qu'il est difficile de refactoriser automatiquement. Voir ma question 2317579 qui a été étrangement reprise par les gens de Smalltalk.
Dan Rosenstark
4
Oui, mais utiliser ces chaînes ne serait pas dans l'esprit du langage C #, c'est simplement une mauvaise pratique.
Il regroupe les valeurs visuellement comme un tout
Il effectue une vérification au moment de la compilation (contrairement à l'utilisation de symboles uniquement)
Je peux facilement accéder à la liste de toutes les valeurs possibles: juste MY_ENUM
Je peux facilement accéder à des valeurs distinctes: MY_VALUE_1
Il peut avoir des valeurs de tout type, pas seulement de Symbol
Les symboles peuvent être meilleurs car vous n'avez pas à écrire le nom de la classe externe, si vous l'utilisez dans une autre classe ( MyClass::MY_VALUE_1)
Je pense que c'est la meilleure réponse. La fonctionnalité, la syntaxe et la surcharge minimale de code se rapprochent le plus de Java / C #. Vous pouvez également imbriquer les définitions encore plus profondément qu'un niveau et toujours récupérer toutes les valeurs avec MyClass :: MY_ENUM.flatten. En guise de remarque, j'utiliserais ici des noms en majuscules, comme c'est la norme pour les constantes en Ruby. MyClass :: MyEnum peut être confondu avec une référence à une sous-classe.
Janosch
@Janosch, j'ai mis à jour les noms. merci pour la suggestion
Alexey
Je suis toujours un peu confus, et le lien 410'd (non, pas 404). Pourriez-vous donner des exemples sur la façon dont cette énumération serait utilisée?
Shelvacu
17
Si vous utilisez Rails 4.2 ou supérieur, vous pouvez utiliser les énumérations Rails.
Rails a maintenant des énumérations par défaut sans avoir besoin d'inclure de gemmes.
Ceci est très similaire (et plus avec des fonctionnalités) aux énumérations Java, C ++.
Comme vous l'avez dit - pas utile si l'OP n'utilise pas Rails (ou plus précisément l'objet n'est pas de type ActiveRecord). Juste expliquer mon downvote est tout.
Ger
2
Ce ne sont pas des énumérations dans Ruby, c'est une interface ActiveRecord avec Enums dans votre base de données. Pas une solution généralisable qui peut être appliquée dans tout autre cas d'utilisation.
Adam Lassek
J'ai déjà mentionné cela dans ma réponse.
vedant
C'est la meilleure réponse IFF en utilisant Rails.
theUtherSide
Je ne l'aime pas car il doit être stocké dans une base de données Rails (pour fonctionner) et parce qu'il permet de créer de nombreuses instances de la Conversationclasse - je crois qu'il ne doit autoriser qu'une seule instance.
prograils
8
C'est mon approche des énumérations en Ruby. J'allais pour court et doux, pas nécessairement le plus C-like. Des pensées?
À mon humble avis, cela reproduit de très près l'utilisation et le but (sécurité du type) de Java, également, de préférence, les constantes peuvent être définies comme suit:class ABC; end
wik
8
Je sais que cela fait longtemps que le gars n'a pas posté cette question, mais j'avais la même question et ce post ne m'a pas donné la réponse. Je voulais un moyen facile de voir ce que le nombre représente, une comparaison facile et surtout la prise en charge d'ActiveRecord pour la recherche en utilisant la colonne représentant l'énumération.
Je n'ai rien trouvé, j'ai donc fait une implémentation géniale appelée yinum qui a permis tout ce que je cherchais. Fait des tonnes de spécifications, donc je suis sûr que c'est sûr.
Si vous vous inquiétez des fautes de frappe avec des symboles, assurez-vous que votre code lève une exception lorsque vous accédez à une valeur avec une clé inexistante. Vous pouvez le faire en utilisant fetchplutôt que []:
my_value = my_hash.fetch(:key)
ou en faisant le hachage lever une exception par défaut si vous fournissez une clé inexistante:
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
Si le hachage existe déjà, vous pouvez ajouter un comportement de levée d'exception:
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
Normalement, vous n'avez pas à vous soucier de la sécurité des fautes de frappe avec les constantes. Si vous mal orthographiez un nom constant, cela déclenchera généralement une exception.
Il semble que vous préconisiez d'émuler des énumérations avec des hachages , sans le dire explicitement. Ce serait une bonne idée de modifier votre réponse pour le dire. (Je aussi ai actuellement un besoin de quelque chose comme énumérations en Ruby, et ma première approche pour résoudre c'est à l'aide hash: FOO_VALUES = {missing: 0, something: 1, something_else: 2, ...}Ceci définit les symboles clés. missing, somethingEtc., et rend également comparables par les valeurs associées.)
Teemu Leisti
Je veux dire, sans le dire au tout début de la réponse.
Teemu Leisti
4
Quelqu'un est allé de l'avant et a écrit un joyau de rubis appelé Renum . Il prétend obtenir le comportement similaire à Java / C # le plus proche. Personnellement, j'apprends encore Ruby, et j'ai été un peu choqué quand j'ai voulu faire qu'une classe spécifique contienne une énumération statique, peut-être un hachage, qu'elle ne soit pas exactement facilement trouvée via google.
Je n'ai jamais eu besoin d'une énumération en Ruby. Les symboles et les constantes sont idiomatiques et résolvent les mêmes problèmes, non?
Chuck
Probablement Chuck; mais googler pour une énumération en rubis ne vous mènera pas si loin. Il vous montrera les résultats de la meilleure tentative des gens pour un équivalent direct. Ce qui me fait me demander, peut-être qu'il y a quelque chose de bien à regrouper le concept.
dlamblin
@Chuck Les symboles et les constantes n'imposent pas, par exemple, qu'une valeur doit faire partie d'un petit ensemble de valeurs.
David Moles
3
Tout dépend de la façon dont vous utilisez les énumérations Java ou C #. La façon dont vous l'utiliserez dictera la solution que vous choisirez dans Ruby.
Pourquoi ne pas utiliser des symboles Set[:a, :b, :c]?
Dan Rosenstark
2
Bien meilleure pratique pour utiliser des symboles ici, OMI.
Collin Graves
3
Récemment, nous avons publié une gemme qui implémente Enums in Ruby . Dans mon article, vous trouverez les réponses à vos questions. J'y ai également expliqué pourquoi notre implémentation est meilleure que celles existantes (en fait, il existe de nombreuses implémentations de cette fonctionnalité dans Ruby encore comme des gemmes).
# bar.rb
require 'ostruct'# not needed when using Rails# by patching Array you have a simple way of creating a ENUM-styleclassArraydef to_enum(base=0)OpenStruct.new(map.with_index(base).to_h)endendclassBar
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"endendend# 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'
Les symboles sont la voie rubis. Cependant, il faut parfois parler à du code C ou à quelque chose ou à Java qui exposent une énumération pour diverses choses.
#server_roles.rbmoduleEnumLikedefEnumLike.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
endend
Mettez-vous en majuscule le deuxième mot dans des variables (par exemple server_Symb) pour une raison particulière? À moins qu'il n'y ait une raison particulière, il est idiomatique que les variables soient snake_case_with_all_lower_caseet que les symboles soient :lower_case.
Andrew Grimm
1
@Andrew; cet exemple a été tiré d'un monde réel et la documentation du protocole réseau a utilisé xxx_Yyy, donc le code dans plusieurs langues a utilisé le même concept afin que l'on puisse suivre les changements de spécification.
Jonke
1
Code golf: server_Symb.each_with_index { |e,i| server_Enum[e] = i}. Pas besoin de i = 0.
Andrew Grimm
2
J'ai implémenté des énumérations comme ça
moduleEnumTypedefself.find_by_id id
if id.instance_of?String
id = id.to_i
end
values.each do|type|if id == type.id
return type
endendnilenddefself.values
[@ENUM_1,@ENUM_2]endclassEnum
attr_reader :id,:label
def initialize id, label
@id= id
@label= label
endend@ENUM_1=Enum.new(1,"first")@ENUM_2=Enum.new(2,"second")end
Cela semble un peu superflu, mais c'est une méthodologie que j'ai utilisée à quelques reprises, en particulier lorsque j'intègre avec xml ou quelque chose du genre.
Je ne conseillerais pas cette approche, car elle repose sur vous en définissant manuellement les valeurs et en vous assurant d'obtenir la bonne commande :VAL. Il serait préférable de commencer avec un tableau et de construire le hachage en utilisant.map.with_index
DaveMongoose
1
Le point exact est de vous lier à une valeur dictée par des tiers. Il ne s'agit pas d'extensibilité en soi, mais de devoir faire face à des contraintes externes qui ont un impact sur la calculabilité dans les limites de votre processus.
jjk
Bon point! Dans ce cas, il est certainement logique de spécifier les valeurs, mais je serais enclin à faire la recherche inversée avec .keyou .invertplutôt qu'avec une :VALclé ( stackoverflow.com/a/10989394/2208016 )
DaveMongoose
Ouais, c'est (de retour à vous) un bon point. Mon rubis était inélégant et peu maniable. Voudrait utiliser keyouinvert
jjk
1
La plupart des gens utilisent des symboles (c'est la :foo_barsyntaxe). Ce sont en quelque sorte des valeurs opaques uniques. Les symboles n'appartiennent à aucun type de style enum, ils ne sont donc pas vraiment une représentation fidèle du type enum de C, mais c'est à peu près aussi bon que possible.
Parfois, tout ce dont j'ai besoin est de pouvoir récupérer la valeur d'énumération et identifier son nom de manière similaire à Java World.
moduleEnumdef get_value(str)
const_get(str)enddef get_name(sym)
sym.to_s.upcase
endendclassFruits
include Enum
APPLE ="Delicious"
MANGO ="Sweet"endFruits.get_value('APPLE')#'Delicious'Fruits.get_value('MANGO')# 'Sweet'Fruits.get_name(:apple)# 'APPLE'Fruits.get_name(:mango)# 'MANGO'
Pour moi, cela sert le but de l'énumération et le maintient très extensible aussi. Vous pouvez ajouter plus de méthodes à la classe Enum et l'alto les obtenir gratuitement dans toutes les énumérations définies. par exemple. get_all_names et des trucs comme ça.
Une autre approche consiste à utiliser une classe Ruby avec un hachage contenant des noms et des valeurs comme décrit dans le billet de blog RubyFleebie suivant . Cela vous permet de convertir facilement entre des valeurs et des constantes (surtout si vous ajoutez une méthode de classe pour rechercher le nom d'une valeur donnée).
Je pense que la meilleure façon d'implémenter l'énumération comme les types est avec des symboles car ils se comportent à peu près comme des entiers (quand il s'agit de performace, object_id est utilisé pour faire des comparaisons); vous n'avez pas à vous soucier de l'indexation et ils ont l'air vraiment bien dans votre code xD
Une autre façon d'imiter une énumération avec une gestion cohérente de l'égalité (adoptée sans vergogne par Dave Thomas). Permet des énumérations ouvertes (un peu comme les symboles) et des énumérations fermées (prédéfinies).
Réponses:
Deux manières. Symboles (
:foo
notation) ou constantes (FOO
notation).Les symboles sont appropriés lorsque vous souhaitez améliorer la lisibilité sans encombrer le code avec des chaînes littérales.
Les constantes sont appropriées lorsque vous avez une valeur sous-jacente qui est importante. Déclarez simplement un module pour contenir vos constantes, puis déclarez les constantes à l'intérieur.
la source
:minnesota.to_s
lors de l'enregistrement dans une base de données pour enregistrer la version chaîne du symbole. Rails, je crois, a des méthodes d'aide pour gérer certains de ces problèmes.Je suis surpris que personne n'ait offert quelque chose comme ce qui suit (récolté à partir de la gemme RAPI ):
Qui peut être utilisé comme ceci:
Exemple:
Cela fonctionne bien dans les scénarios de base de données, ou lorsqu'il s'agit de constantes / énumérations de style C (comme c'est le cas lors de l'utilisation de FFI , que RAPI utilise largement).
De plus, vous n'avez pas à vous soucier des fautes de frappe provoquant des échecs silencieux, comme vous le feriez avec une solution de type hachage.
la source
La façon la plus idiomatique de le faire est d'utiliser des symboles. Par exemple, au lieu de:
... vous pouvez simplement utiliser des symboles:
C'est un peu plus ouvert que les énumérations, mais cela correspond bien à l'esprit Ruby.
Les symboles fonctionnent également très bien. La comparaison de deux symboles pour l'égalité, par exemple, est beaucoup plus rapide que la comparaison de deux chaînes.
la source
J'utilise l'approche suivante:
Je l'aime pour les avantages suivants:
MY_ENUM
MY_VALUE_1
Les symboles peuvent être meilleurs car vous n'avez pas à écrire le nom de la classe externe, si vous l'utilisez dans une autre classe (
MyClass::MY_VALUE_1
)la source
Si vous utilisez Rails 4.2 ou supérieur, vous pouvez utiliser les énumérations Rails.
Rails a maintenant des énumérations par défaut sans avoir besoin d'inclure de gemmes.
Ceci est très similaire (et plus avec des fonctionnalités) aux énumérations Java, C ++.
Cité sur http://edgeapi.rubyonrails.org/classes/ActiveRecord/Enum.html :
la source
Conversation
classe - je crois qu'il ne doit autoriser qu'une seule instance.C'est mon approche des énumérations en Ruby. J'allais pour court et doux, pas nécessairement le plus C-like. Des pensées?
la source
Découvrez la gemme rubis-enum, https://github.com/dblock/ruby-enum .
la source
La meilleure approche légère serait peut-être
De cette façon, les valeurs ont des noms associés, comme dans Java / C #:
Pour obtenir toutes les valeurs, vous pouvez faire
Si vous voulez une valeur ordinale d'une énumération, vous pouvez le faire
la source
class ABC; end
Je sais que cela fait longtemps que le gars n'a pas posté cette question, mais j'avais la même question et ce post ne m'a pas donné la réponse. Je voulais un moyen facile de voir ce que le nombre représente, une comparaison facile et surtout la prise en charge d'ActiveRecord pour la recherche en utilisant la colonne représentant l'énumération.
Je n'ai rien trouvé, j'ai donc fait une implémentation géniale appelée yinum qui a permis tout ce que je cherchais. Fait des tonnes de spécifications, donc je suis sûr que c'est sûr.
Quelques exemples de fonctionnalités:
la source
Si vous vous inquiétez des fautes de frappe avec des symboles, assurez-vous que votre code lève une exception lorsque vous accédez à une valeur avec une clé inexistante. Vous pouvez le faire en utilisant
fetch
plutôt que[]
:ou en faisant le hachage lever une exception par défaut si vous fournissez une clé inexistante:
Si le hachage existe déjà, vous pouvez ajouter un comportement de levée d'exception:
Normalement, vous n'avez pas à vous soucier de la sécurité des fautes de frappe avec les constantes. Si vous mal orthographiez un nom constant, cela déclenchera généralement une exception.
la source
FOO_VALUES = {missing: 0, something: 1, something_else: 2, ...}
Ceci définit les symboles clés.missing
,something
Etc., et rend également comparables par les valeurs associées.)Quelqu'un est allé de l'avant et a écrit un joyau de rubis appelé Renum . Il prétend obtenir le comportement similaire à Java / C # le plus proche. Personnellement, j'apprends encore Ruby, et j'ai été un peu choqué quand j'ai voulu faire qu'une classe spécifique contienne une énumération statique, peut-être un hachage, qu'elle ne soit pas exactement facilement trouvée via google.
la source
Tout dépend de la façon dont vous utilisez les énumérations Java ou C #. La façon dont vous l'utiliserez dictera la solution que vous choisirez dans Ruby.
Essayez le
Set
type natif , par exemple:la source
Set[:a, :b, :c]
?Récemment, nous avons publié une gemme qui implémente Enums in Ruby . Dans mon article, vous trouverez les réponses à vos questions. J'y ai également expliqué pourquoi notre implémentation est meilleure que celles existantes (en fait, il existe de nombreuses implémentations de cette fonctionnalité dans Ruby encore comme des gemmes).
la source
Une autre solution utilise OpenStruct. C'est assez simple et propre.
https://ruby-doc.org/stdlib-2.3.1/libdoc/ostruct/rdoc/OpenStruct.html
Exemple:
la source
Les symboles sont la voie rubis. Cependant, il faut parfois parler à du code C ou à quelque chose ou à Java qui exposent une énumération pour diverses choses.
Cela peut ensuite être utilisé comme ceci
Ceci peut bien sûr être rendu abstrait et vous pouvez lancer notre propre classe Enum
la source
server_Symb
) pour une raison particulière? À moins qu'il n'y ait une raison particulière, il est idiomatique que les variables soientsnake_case_with_all_lower_case
et que les symboles soient:lower_case
.server_Symb.each_with_index { |e,i| server_Enum[e] = i}
. Pas besoin dei = 0
.J'ai implémenté des énumérations comme ça
puis ses opérations faciles à faire
...
...
la source
Cela semble un peu superflu, mais c'est une méthodologie que j'ai utilisée à quelques reprises, en particulier lorsque j'intègre avec xml ou quelque chose du genre.
Cela me donne la rigueur d'un ac # enum et c'est lié au modèle.
la source
:VAL
. Il serait préférable de commencer avec un tableau et de construire le hachage en utilisant.map.with_index
.key
ou.invert
plutôt qu'avec une:VAL
clé ( stackoverflow.com/a/10989394/2208016 )key
ouinvert
La plupart des gens utilisent des symboles (c'est la
:foo_bar
syntaxe). Ce sont en quelque sorte des valeurs opaques uniques. Les symboles n'appartiennent à aucun type de style enum, ils ne sont donc pas vraiment une représentation fidèle du type enum de C, mais c'est à peu près aussi bon que possible.la source
Production:
1 - a
2 - b
3 - c
4 - d
la source
to_enum
vous donne un enumera teur , alors queenum
dans le C # / Java sens est une enumera tionProduction:
la source
Parfois, tout ce dont j'ai besoin est de pouvoir récupérer la valeur d'énumération et identifier son nom de manière similaire à Java World.
Pour moi, cela sert le but de l'énumération et le maintient très extensible aussi. Vous pouvez ajouter plus de méthodes à la classe Enum et l'alto les obtenir gratuitement dans toutes les énumérations définies. par exemple. get_all_names et des trucs comme ça.
la source
Une autre approche consiste à utiliser une classe Ruby avec un hachage contenant des noms et des valeurs comme décrit dans le billet de blog RubyFleebie suivant . Cela vous permet de convertir facilement entre des valeurs et des constantes (surtout si vous ajoutez une méthode de classe pour rechercher le nom d'une valeur donnée).
la source
Je pense que la meilleure façon d'implémenter l'énumération comme les types est avec des symboles car ils se comportent à peu près comme des entiers (quand il s'agit de performace, object_id est utilisé pour faire des comparaisons); vous n'avez pas à vous soucier de l'indexation et ils ont l'air vraiment bien dans votre code xD
la source
Une autre façon d'imiter une énumération avec une gestion cohérente de l'égalité (adoptée sans vergogne par Dave Thomas). Permet des énumérations ouvertes (un peu comme les symboles) et des énumérations fermées (prédéfinies).
la source
Essayez l'inum. https://github.com/alfa-jpn/inum
voir plus https://github.com/alfa-jpn/inum#usage
la source