验证关联的唯一性

时间:2012-01-22 21:58:03

标签: ruby-on-rails ruby-on-rails-3

鉴于以下类别:

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

如何在Rails上验证之前的语句(在图像中)?

在更新时,在应用程序上添加以下验证将无效:

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

当尝试将应用程序更改为同一公司候选人的其他JobOffer时,公司将返回该公司。

我也试过在Application上做这样的事情:

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

但它也没有用。 任何想法解决这个问题,而不必使用10行蹩脚的代码?

4 个答案:

答案 0 :(得分:14)

可能有许多可接受的方法可以解决您的问题,但我认为最重要的是您尝试在没有(直接)拥有所有属性的表格上强制执行唯一性约束(两者都是companyuser)。我将company信息取消规范化到应用程序表(user_idjob_offer_idcompany_id),并始终将其设置为before_save回调匹配job_offer' s company。然后你应该能够使用范围唯一性验证:

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

答案 1 :(得分:0)

这就是我将如何构建模型:

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

这应该有效! 顺便说一句。我将调用该应用程序以避免命名混淆(rails已经有application.rb

答案 2 :(得分:0)

如图所示,候选人和工作机会将有许多应用程序和候选人只能申请每个公司一份工作机会。因此,在应用程序中验证作用于作业的候选者的唯一性可能会这样做。

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

这将阻止应用程序与同一工作机会的同一候选人相关联。候选人可以申请其他工作机会,对吗?

正如@ez。所指出的那样,将应用程序重命名为适当的东西会更好。

希望这有帮助。

答案 3 :(得分:0)

对于今天发现这一点的人。答案是检查何时存在(防止多个)&amp;当应用程序本身切换时跳过。

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