Rails: valider l'unicité de deux colonnes (ensemble)

Réponses:

230

Vous pouvez utiliser une validation d' unicité avec l' scopeoption.

De plus, vous devez ajouter un index unique à la base de données pour empêcher les nouveaux enregistrements de passer les validations lorsqu'ils sont vérifiés en même temps avant d'être écrits:

class AddUniqueIndexToReleases < ActiveRecord::Migration
  def change
    add_index :releases, [:country, :medium], unique: true
  end
end



class Release < ActiveRecord::Base
  validates :country, uniqueness: { scope: :medium }
end
tompave
la source
+1 pour l'index, mais -1 pour le uniquecar il n'est pas reconnu. Pour cette partie, j'ai utilisé la réponse ci-dessous.
Aleks
7
Oui, désolé, la clé de validation devrait être uniqueness, non unique. Voir la documentation liée. Fixer la réponse.
tompave le
1
Hm, gentil, merci :) Pour me répéter - mettre l'index amène la solution au niveau suivant, et pas seulement comme d'autres solutions de "codage" que j'ai rencontrées, avant de trouver cette réponse. +1 pour ça
Aleks
70

Toutes les réponses ci-dessus ne permettent pas de valider l'unicité de plusieurs attributs dans un modèle. Le code ci-dessous a l'intention de dire comment utiliser plusieurs attributs dans une portée.

validates :country, uniqueness: { scope: [:medium, :another_medium] }

Il valide l'unicité de countrydans toutes les lignes avec des valeurs de mediumet another_medium.

Remarque: n'oubliez pas d'ajouter un index sur la colonne ci-dessus, cela assure une récupération rapide et ajoute une validation au niveau de la base de données pour les enregistrements uniques.

Mise à jour: pour ajouter un index lors de la création d'une table

t.index [:medium, :another_medium], unique: true
Aamir
la source
41

Vous pouvez passer un :scopeparamètre à votre validateur comme ceci:

validates_uniqueness_of :medium, scope: :country

Consultez la documentation pour plus d'exemples.

KM Rakibul Islam
la source
8
@DennisBest Cela "fonctionne", mais cela ne protège pas contre les conditions de course. Si deux clients effectuent des demandes simultanées, ils pourraient tous les deux réussir la validation si aucun d'entre eux n'est validé dans la base de données avant que l'autre ne soit validé. Vous avez également besoin d'une contrainte unique de base de données comme dans la réponse de tompave.
soupdog