Search code examples
ruby-on-railsrails-activerecordpolymorphic-associations

Validation for the count of has_many relationship in Rails


I have been through other questions, but the scenario is little different here:

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

Now, consider User.find(2) that already has two documents, so doing the following:

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

This successfully creates the document, and doesn't validate the attachable: User. After the document is created in the database, both user & Document.last are invalid, but of what use, they have been created now.

I'm trying to create a Document object on the run time, and that may be causing it, but for that purpose, I'm using size instead of count in my validation.


Solution

  • inverse_of to rescue here again.

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

    Doing user.documents << Document.new(file: file) won't change the count for the associated documents of a user unless a document is actually created, and since the count will remain 2 while creating a 3rd document, so Rails won't stop you creating a third document associated with the user, killing the very purpose of putting the validation.

    So following is what I did:

    # In User model
    has_many :documents, as: :attachable, inverse_of: :attachable
    
    # In Document model
    belongs_to :attachable, polymorphic: true, inverse_of: :attachments
    

    Related article to read: https://robots.thoughtbot.com/accepts-nested-attributes-for-with-has-many-through