web-dev-qa-db-fra.com

Valider la présence du champ uniquement si un autre champ est vide - Rails

J'ai un formulaire avec un numéro de portable/cellulaire et un numéro de téléphone à la maison.

Je souhaite que la présence du numéro de portable/portable ne soit validée que si le numéro de téléphone a été laissé en blanc ou inversement.

Mes validations actuelles pour ces champs sont les suivantes.

validates_presence_of :mobile_number
validates_presence_of :home_phone

validates_length_of :home_phone, :minimum => 12, :maximum => 12
validates_length_of :mobile_number, :minimum => 10, :maximum => 10, :allow_blank => true

validates_format_of :home_phone, :with => /\A[0-9]{2}\s[0-9]{4}\s[0-9]{4}/, :message => "format should be 02 9999 9999"

Je pensais que je pouvais avoir quelque chose comme ce qui suit, mais je ne savais pas trop comment faire cela.

validates_presence_of :mobile_number, :unless => :home_phone.blank?

J'utilise Rails 3.

51
Robert B

Vous n'avez pas besoin d'un lambda. Cela fera:

validates_presence_of :mobile_number, :unless => :home_phone?

De plus, tous les validateurs prennent la même chose si/sauf les options, vous pouvez donc les rendre conditionnelles à volonté.

Mise à jour: En regardant cette réponse quelques jours plus tard, je vois que je devrais expliquer pourquoi cela fonctionne:

  • Si vous définissez l'option :unless du validateur en tant que symbole, Rails recherchera une méthode d'instance portant ce nom, l'invoquera sur l'instance en cours de validation (au moment de la validation) et n'effectuera la validation que si la méthode renvoie false.
  • ActiveRecord crée automatiquement des méthodes de point d'interrogation pour chacun des attributs de votre modèle. Par conséquent, l'existence d'une colonne home_phone dans la table de votre modèle force Rails à créer une méthode pratique #home_phone?. Cette méthode retourne true si et seulement si home_phone est présent (c'est-à-dire non vide). Si l'attribut home_phone est nil ou s'il s'agit d'une chaîne vide ou d'un espace vide, home_phone? retournera faux.

UPDATE: Confirmation que cette ancienne technique continue de fonctionner dans Rails 5.

110
Rob Davis

Vous devez utiliser un objet lambda/Proc:

validates_presence_of :mobile_number, :unless => lambda { self.home_phone.blank? }
21
Ryan Bigg

À partir de Rails 4, vous pouvez passer un bloc à la présence. En résumé:

validates :mobile_number, presence: {unless: :home_phone?}

De plus, :home_phone? renvoie false pour nil ou vide.

7
IAmNaN

Voici une autre manière qui fonctionne dans Rails 4

  validates_presence_of :job, if: :executed_at?

  validates :code,
            presence: true,
            length:  { minimum: 10, maximum: 50 },
            uniqueness: { case_sensitive: false },
            numericality: { only_integer: true }
2
Chris Hough

une solution courte:

validates_presence_of :mobile_number, unless: -> { home_phone.blank? }
0
John