Validate uniqueness of in association

本秂侑毒 提交于 2021-01-20 18:05:22

问题


Given the following classes:

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

class JobOffer
  belongs_to :company
end

class Application
  belongs_to :candidate
  belongs_to :job_offer
end

enter image description here

How can I validate the previous statement (in the image) on Rails?

Adding the following validation on Application won't work when updating:

def validate_uniqueness_of_candidate_within_company
  errors.add(:job_offer_id, "...") if candidate.companies.include?(company)
end

Cause when trying to change the application to a different JobOffer of the same company candidate.companies will return that company.

I also tried doing something like this on Application:

validates_uniqueness_of :user_id, :scope => {:job_offer => :company_id}

But it didn't work either. Any ideas to solve this without having to use 10 lines of crappy code?


回答1:


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



回答2:


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




回答3:


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.




回答4:


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


来源:https://stackoverflow.com/questions/8965089/validate-uniqueness-of-in-association

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!