Comment puis-je spécifier et valider une énumération dans 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 cela. STATUS_OPTIONS = {: oui,: non,: peut-être}

1) Je ne suis pas sûr de savoir comment valider cela avant qu'un utilisateur insère une participation? Fondamentalement, une énumération en java mais comment pourrais-je le faire dans rails?

21
demandé sur mu is too short 2011-11-16 09:02:46

7 réponses

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

class Attend < ActiveRecord::Base

  STATUS_OPTIONS = %w(yes no maybe)

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

end

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

33
répondu mnelson 2011-11-16 05:11:06

Maintenant que Rails 4.1 inclut des énumérations, vous pouvez faire ce qui suit:

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

Qui vous fournit alors une portée (ie: Attend.yes, Attend.no, Attend.maybe pour chacun une méthode checker pour voir si un certain statut est défini (ie: #yes?, #no?, #maybe?), avec les méthodes de setter d'attribut (ie: #yes!, #no!, #maybe!).

Rails de Docs sur les enums

55
répondu barnett 2016-06-14 23:31:36

C'est ainsi 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

Assister.tailles vous donne la cartographie.

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

Voir plus dans les Rails doc

8
répondu Benny 2015-01-10 10:54:41

, Vous pouvez utiliser une colonne de type chaîne pour le statut et puis l':inclusion option pour validates pour s'assurer que vous obtenez seulement ce que vous attendez:

class Attend < ActiveRecord::Base
    validates :size, :inclusion => { :in => %w{yes no maybe} }
    #...
end
4
répondu mu is too short 2014-11-05 11:32:40

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'enum, les validations et utiliser les valeurs dans 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 pouvez également utiliser STATUS_OPTIONS plus tard, comme pour créer une liste déroulante. Si vous voulez exposer vos valeurs à l'utilisateur, vous pouvez toujours Mapper comme ceci:

STATUS_OPTIONS.map {|s| s.to_s.titleize }
2
répondu Ken Stipek 2014-11-25 23:13:02

Pour les énumérations Dans ActiveModels, vous pouvez utiliser cette gemme Enumerize

0
répondu Yoihito 2014-11-25 23:05:22

Après quelques recherches, Je ne pouvais pas trouver un one-liner dans le modèle pour l'aider à se produire. À l'heure actuelle, Rails fournit des énumérations, mais pas un moyen complet de valider des 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:

assister à.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

Aussi, je vais faire un chèque contre les paramètres d'entrée non valide et envoyer le résultat (si nécessaire) au modèle, donc 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
répondu Ruby Racer 2017-10-02 11:25:08