2009-07-24 7 views
3

J'ai des éléments dans mon schéma de base de données qui sont un nombre entier et sont mis à un nombre spécifique corrélant à un élément. Par exemple, une colonne nommée type_rendez-vous peut avoir la valeur 0 = Inconnu, 1 = Médical, 3 = Essai, etc ... Je ne veux pas utiliser de nombres magiques dans mon code de rails et préférerais une solution de type Enum à rendre le code plus facile à maintenir et à lire. En outre, il y a plus d'une table qui a cette colonne de type de rendez-vous, ainsi je veux pouvoir employer le "enum" pour adresser d'autres colonnes aussi bien.Rails global enums?

Je pensais avoir un objet global enum puisque je devrais avoir accès à ceci dans mon modèle, contrôleur et vue. Il est peut-être moins probable que je doive y accéder dans mon modèle, mais certainement dans le contrôleur et la vue.

Existe-t-il un bon moyen de gérer cela?

Répondre

4

Il peut y avoir moins de chances que je dois l'accès dans mon modèle, mais certainement dans le contrôleur et la vue.

Êtes-vous sûr? Lorsque vous parlez de base de données et de schéma, vous parlez de la partie Modèle de votre application. Je pense que le meilleur endroit pour stocker ces variables serait le modèle qui les utilise.

Si ces variables appartiennent à un seul modèle, vous pouvez les stocker directement dans le modèle lui-même:

class Item < ActiveRecord::Base 
    STATUS_UNKNOWN = 0 
    STATUS_MEDICAL = 3 
end 

Ensuite, vous pouvez référencer les valeurs à l'intérieur et à l'extérieur du champ d'application du modèle

class Item 
    def my_method 
    STATUS_UNKNOWN 
    end 
end 

Item::STATUS_UNKNOWN # => 0 
Item.new.my_method # => 0 

Quand il est une énumération de valeurs, les rubisistes utilisent souvent des hachages ou des tableaux.

class Item 
    AVAILABLE_STATUSES = { :unkwnown => 0, :medical => 3 } 

    def self.statuses 
    self.AVAILABLE_STATUSES.keys.sort 
    end 

    def self.status_value(key) 
    self.AVAILABLE_STATUSES[:key] 
    end 

end 

Item::AVAILABLE_STATUS # => { :unkwnown => 0, :medical => 3 } 
Item.statuses # => [:medical, :unkwnown] 
Item.status_value(:medical) # => 3 

Si plus d'une action modèle de la même logique, vous pouvez le mettre dans un module et mélanger le module dans tous les modèles qui l'exige.

+0

Où puis-je mettre le module? En lib /? – intargc

+0

Vous pouvez utiliser/lib, bien que je préfère généralement créer un dossier nommé/apps/concerns avec tous les mixins personnalisés du contrôleur/modèle. –

0

Mon appel serait de le mettre dans le modèle associé

1

ce code pourrait vous aider ...

d'abord, créez dans le dossier lib un fichier nommé:

integer_to_enum.rb 

En le fichier mis ce code:

module IntegerToEnum 

    class << self 

    def included(klass) 
     klass.extend(ModelClassMethods) 
    end 

    end 

    module ModelClassMethods 

    def fields_to_enum(options={}) 
     class_eval <<-end_eval 
     def set_enum_options 
      @enum_options = #{options.inspect} 
     end 
     end_eval 

     options.each_pair do |k,v| 
     class_eval <<-end_eval 
      def #{k.to_s} 
      self.set_enum_options 
      @enum_options[:#{k.to_s}][read_attribute(:#{k.to_s}).to_i] 
      end 

      def #{k.to_s}=(v) 
      self.set_enum_options 
      unless @enum_options[:#{k.to_s}].include?(v) 
       return false 
      end 

      write_attribute(:#{k.to_s}, @enum_options[:#{k.to_s}].index(v)) 
      @#{k.to_s} 
      end 
     end_eval 
     end 
    end 
    end 

end 

sur le enviroment.rb, mettre cela au fond, après « fin '

ActiveRecord::Base.send :include, IntegerToEnum 

Enfin, dans le modèle que vous voulez 'traduire' la vente de champ entier:

class YourModel < ActiveRecord::Base 

    fields_to_enum :appointment_type => [:unknown, :medical, :trial], :other_field_type => [:type_a, :type_b, :type_c] 

end 

Avec cela, vous pouvez faire quelque chose comme:

m = YourModel.find(1) 
m.appointment_type #=> :unknown 
m.appointment_type = :trial #=> :trial 
m.save #=> and this will save with the index value of the array definition, since ':trial' is in the 3er position, the sql resulting will save with this number 

et que tout..espérons pouvoir vous aider

+0

Notez que ce code pourrait être beaucoup mieux et élégant, désolé mon anglais;) –

0

Vous pouvez avoir une table qui contient toutes ces informations et mettre en cache la sélection de la table initiale sur le chargement de l'environnement. De cette façon, vous pouvez même implémenter l'intégrité référentielle entre la table appointment_types et la table appointment_type_id sur d'autres tables.