2017-04-18 4 views
1

Supposons que je deux classesRails one-to-many: Valider la valeur du champ

class student < ApplicationRecord 
     has_many :books 
    end 

    class Book < ApplicationRecord 
     belongs_to :student 
    end 

Chaque livre sera une variable booléenne indiquant read si le livre a été lu ou non. Chaque étudiant peut seulement lire un livre. Si l'un des livres d'un élève est marqué comme lu, ses autres livres ne peuvent plus être lus.

Existe-t-il une validation PSQL ou active-record pour permettre cette contrainte? En particulier, book.update_attributes!(read: true) fera une vérification sur d'autres livres associés. Les contraintes de base de données seraient grandement préférées.

Merci beaucoup!

Mise à jour énoncé du problème:

lecture devient un read_at d'horodatage et book.update_attributes!(read_at: Time.zone.now) fera un chèque si l'étudiant a lu d'autres livres auparavant.

+0

Ainsi, lorsque un enregistrement est créé dans la table Book, 'read' serait défini sur' false', et mis à jour à 'true' quand ce livre est lu ... une fois qu'un livre a été lu, toute tentative de modification d'un livre différent' read 'value à' true' devrait échouer, est-ce co rrect? – skwidbreth

+0

Les livres sont créés avec la valeur par défaut de lecture sur false et sont mis à jour à true lorsqu'ils sont lus. Toute tentative de changement d'un livre différent de la valeur de lecture du même élève à true devrait échouer – LOCKLOCK

Répondre

1

Ajouter un index partiel unique sur un champ champ read booléen et entier student_id où lecture est égal vrai

add_column :books, :read, :boolean, null: false, default: false 
add_index :books, [:student_id, :read], unique: true, where: "read=true" 

Dans le modèle livre ajouter validation unique qui ne fonctionne que lorsque book.read == true

validates :read, uniqueness: { scope: :student_id }, if: -> (book) { book.read } 
+0

Ceci valide l'unicité. Savez-vous s'il y a quelque chose allow_false: true et allow_nil: true? – LOCKLOCK

+0

Oui, vous avez raison. J'ai mis à jour ma réponse et je l'ai testée. –

+0

'validates: read, unicité: {scope:: student_id}, si: 'read.present?'' Cela fonctionne aussi bien je pense. – LOCKLOCK