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?
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
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!
).
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}
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
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 }
Pour les enums dans ActiveModels, vous pouvez utiliser cette gemme Enumerize
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