1

Je suis passé par d'autres questions, mais le scénario est peu différent ici:validation pour le compte de la relation has_many dans Rails

class User < ApplicationRecord 
    has_many :documents, as: :attachable 

    validate :validate_no_of_documents 

    private 
    def validate_no_of_documents 
    errors.add(:documents, "count shouldn't be more than 2") if self.documents.size > 2 
    end 
end 


class Document < ApplicationRecord 
    belongs_to :attachable, polymorphic: true 

    validates_associated :attachable 
end 

Maintenant, considérons User.find(2) qui a déjà deux documents, faisant ce qui suit:

user.documents << Document.new(file: File.open('image.jpg', 'rb')) 

Ceci crée avec succès le document, et ne valide pas le attachable: User. Une fois le document créé dans la base de données, les deux user & Document.last ne sont pas valides, mais à quoi bon ils ont été créés maintenant.

J'essaye de créer un objet Document sur l'exécution, et cela peut être à l'origine, mais pour cela, j'utilise size au lieu de count dans ma validation.

+0

si vous faites 'si self.documents.size> 2' à' si self.documents.size> 1 ', il va arrêter de créer un troisième document pour le même utilisateur. La méthode de validation pour l'utilisateur est déclenchée avant la création de 'Document'. – kiddorails

+0

Avez-vous essayé de mettre' validates_associated: user' dans 'document.rb'? – Pavan

+0

@Pavan 'validates_associated: user' wont 'fonctionnent dans' Document' pour' attachable 'polymorphe. 'user' sera indéfini. – kiddorails

Répondre

2

inverse_of pour sauver ici encore.

user = User.find(1) # This user has already 2 associated documents. 

Faire user.documents << Document.new(file: file) ne changera pas le compte pour les documents associés d'un utilisateur à moins qu'un document est effectivement créé, et que le nombre restera 2 tout en créant un 3ème document si Rails ne vous empêchera pas créer un troisième document associé à l'utilisateur, tuant l'objectif même de mettre la validation.

Voici donc ce que je faisais:

# In User model 
has_many :documents, as: :attachable, inverse_of: :attachable 

# In Document model 
belongs_to :attachable, polymorphic: true, inverse_of: :attachments 

Article connexe à lire: https://robots.thoughtbot.com/accepts-nested-attributes-for-with-has-many-through

0

Vous pouvez utiliser une validation standard pour cela, plutôt que d'une coutume un:

validates :documents, length: { maximum: 2 } 

Vous pouvez toujours envelopper cela dans une transaction, bien que je suis un peu surpris qu'il ne roule pas correctement le dos Document sauvegardé s'il n'est pas valide.

+0

J'ai essayé celui-ci aussi, mais ça ne marche pas. –