Validate uniqueness of in association

前端 未结 4 1093
被撕碎了的回忆
被撕碎了的回忆 2021-02-05 12:46

Given the following classes:

class Candidate
  has_many :applications
  has_many :companies, :through => :job_offers
end

class JobOffer
  belongs_to :company         


        
相关标签:
4条回答
  • 2021-02-05 13:29

    For anyone finding this today. The answer is to check when there are pre-existing (prevents multiple) & skip when the application itself is switching.

    def validate_uniqueness_of_candidate_within_company
      pre_existing = Application.includes(:candidate).includes(job_offer: :company).
        where(companies: { id: self.company.id }).
        where(candidates: { id: self.candidate.id })
    
      if pre_existing.present? && (!pre_existing.map(&:id).include? self.id)
        errors.add(:job_offer_id, "...")
      end
    end
    
    0 讨论(0)
  • 2021-02-05 13:33

    As the image points out, a candidate and a job offer will have many applications & a candidate can only apply to one job offer per company. So, validating uniqueness of candidate scoped to a job offer in application might do.

    class Candidate
      has_many :applications
      has_many :job_offers, :through => :applications
    end
    
    class JobOffer
      belongs_to :company
      has_many :applications
      has_many :candidates, :through => :applications
    end
    
    class Application
      belongs_to :candidate
      belongs_to :job_offer
    
      validates_uniqueness_of :candidate_id, :scope => :job_offer_id
    end
    

    This will prevent an application to be associated to the same candidate for the same job offer. The candidate can apply to other job offers, right?

    And as pointed out by @ez., renaming application to something appropriate is better.

    Hope this helps.

    0 讨论(0)
  • 2021-02-05 13:40

    There are likely many acceptable approaches to solve your issue but I think the bottom line is that you're trying to enforce a uniqueness constraint on the table that doesn't (directly) have all the attributes (both company AND user). I'd de-normalize the company info into the application table (user_id, job_offer_id, company_id) and always set it in a before_save callback to match the job_offer's company. Then you should be able to use the scoped uniqueness validation:

    class JobApplication < ActiveRecord::Base
      belongs_to :user
      belongs_to :job_offer
      belongs_to :hiring_company, :class_name=>"Company", :foreign_key=>"company_id"
    
      before_save :set_hiring_company
    
      def set_hiring_company
       self.hiring_company = job_offer.hiring_company
      end
    
      validates_uniqueness_of :user_id, :scope => :company_id
    end
    
    0 讨论(0)
  • 2021-02-05 13:45

    this is how I will structure the models:

    class Candidate
      has_many :applicatons
      has_many :job_offers
      has_many :offering_companies, :through => :job_offers
    end
    
    class Application
      belongs_to :candidate
    end
    
    class JobOffer
      belongs_to :candidate
      belongs_to :company
    
      validates_uniqueness_of :candidate_id, :scope => :company_id
    end
    
    class Company
    end
    

    This should work! Btw. I will call the application something else to avoid the naming confusion( rails already has application.rb

    0 讨论(0)
提交回复
热议问题