web-dev-qa-db-fra.com

Comment puis-je spécifier et valider une énumération dans les rails?

J'ai actuellement un modèle Attend qui aura une colonne d'état, et cette colonne d'état n'aura que quelques valeurs pour celle-ci. STATUS_OPTIONS = {: oui,: non,: peut-être}

1) Je ne suis pas sûr de savoir comment valider cette information avant qu'un utilisateur insère un événement Participer? Fondamentalement une énumération en Java, mais comment pourrais-je faire cela dans les rails?

23
Kamilski81

Créez un tableau globalement accessible des options souhaitées, puis validez la valeur de votre colonne de statut:

class Attend < ActiveRecord::Base

  STATUS_OPTIONS = %w(yes no maybe)

  validates :status, :inclusion => {:in => STATUS_OPTIONS}

end

Vous pouvez alors accéder aux états possibles via Attend::STATUS_OPTIONS

34
mnelson

Maintenant que Rails 4.1 inclut des énumérations, vous pouvez effectuer les opérations suivantes:

class Attend < ActiveRecord::Base
    enum size: [:yes, :no, :maybe]
    # also can use the %i() syntax for an array of symbols:
    # %i(yes no maybe)
    validates :size, inclusion: { in: sizes.keys }
end

Ce qui vous fournit ensuite une portée (par exemple: Attend.yes, Attend.no, Attend.maybe pour chaque méthode de vérification pour voir si un statut est défini (par exemple: #yes?, #no?, #maybe?), ainsi que des méthodes de définition d'attribut (par exemple: #yes!, #no!, #maybe! ).

Rails Docs sur les enums

60
barnett

C’est ce que j’implémente dans mon projet Rails 4.

class Attend < ActiveRecord::Base
    enum size: [:yes, :no, :maybe]
    validates :size, inclusion: { in: Attend.sizes.keys }
end

Attend.sizes vous donne la cartographie. 

Attend.sizes # {"yes" => 0, "no" => 1, "maybe" => 2}

Voir plus dans doc Rails

9
Benny

Vous pouvez utiliser une colonne de chaîne pour le statut, puis l'option :inclusion POUR validates afin de vous assurer que vous n'obtenez que ce que vous attendez:

class Attend < ActiveRecord::Base
    validates :size, :inclusion => { :in => %w{yes no maybe} }
    #...
end
4
mu is too short

Ce que nous avons commencé à faire est de définir nos éléments enum dans un tableau, puis d’utiliser ce tableau pour spécifier l’énum, ​​les validations et les valeurs de l’application.

STATUS_OPTIONS = [:yes, :no, :maybe]
enum status_option: STATUS_OPTIONS
validates :status_option, inclusion: { in: STATUS_OPTIONS.map {|t| t.to_s } }

De cette façon, vous pourrez également utiliser STATUS_OPTIONS ultérieurement, par exemple pour créer une liste déroulante. Si vous souhaitez exposer vos valeurs à l'utilisateur, vous pouvez toujours mapper comme ceci:

STATUS_OPTIONS.map {|s| s.to_s.titleize }
2
Ken Stipek

Pour les enums dans ActiveModels, vous pouvez utiliser cette gemme Enumerize

0
Yoihito

Après quelques recherches, je ne pouvais pas trouver un modèle unique pour que cela se produise. À l’heure actuelle, Rails fournit des énumérations, mais pas une méthode complète pour valider les valeurs non valides.

J'ai donc opté pour une solution composite: Ajouter une validation dans le contrôleur, avant de définir le strong_params, puis en vérifiant par rapport au modèle.

Donc, dans le modèle, je vais créer un attribut et une validation personnalisée:

attend.rb

enum :status => { your set of values }
attr_accessor :invalid_status

validate :valid_status
#...
private
    def valid_status
        if self.invalid_status == true
            errors.add(:status, "is not valid")
        end
    end

De plus, je vérifierai les paramètres pour une entrée invalide et enverrai le résultat (si nécessaire) au modèle, de sorte qu'une erreur sera ajoutée à l'objet, le rendant ainsi invalide.

attends_controller.rb

private
    def attend_params
        #modify strong_params to include the additional check
        if params[:attend][:status].in?(Attend.statuses.keys << nil) # to also allow nil input
            # Leave this as it was before the check
            params.require(:attend).permit(....) 
        else
            params[:attend][:invalid_status] = true
            # remove the 'status' attribute to avoid the exception and
            # inject the attribute to the params to force invalid instance
            params.require(:attend).permit(...., :invalid_status)
       end
    end
0
Ruby Racer