我有一个名为 Log 的模型,它与 ButtonPress 和 LinkClick 两个模型有关系。我需要验证其中任何一个的存在(出于分析原因,我需要在不使用多态关系的情况下执行此操作)
我的规格文件如下:
RSpec.describe RedirectLog, type: :model do
it { is_expected.to belong_to(:button_press).optional }
it { is_expected.to belong_to(:link_click).optional }
it "has either a button_press or a link_click" do
log = build(:log, button_press: nil, link_click: nil)
expect(log).not_to be_valid
end
结束
为了实现这一目标,我创建了如下模型:
class Log < ApplicationRecord
belongs_to :button_press, optional: true
belongs_to :link_click, optional: true
validates :button_press, presence: true, unless: :link_click
end
当我运行此程序时,出现以下错误:
Failure/Error: it { is_expected.to belong_to(:button_press).optional }
Expected Log to have a belongs_to association called button_press (and for the record not to fail validation if :button_press is unset; i.e., either the association should have been defined with `optional: true`, or there should not be a presence validation on :button_press)
所以简而言之,如果我想验证它的存在,即使是有条件的,我也不能拥有belongs_to关联。我的问题是,Rails 的方法是什么,可以在不使用多态性的情况下对两个 own_to 列之一进行验证?
一种方法是使用自定义验证器。我会用自己的文件等使其完全正式,但为了概念验证,您可以这样做:
class Log < ApplicationRecord
###################################################################
#
# Associations
#
###################################################################
belongs_to :button_press, optional: true
belongs_to :link_click, optional: true
###################################################################
#
# Validations
#
###################################################################
validate :button_press_or_link_click_presence
###################################################################
#
# In-Model Custom Validators (Private)
#
###################################################################
def button_press_or_link_click_presence
self.errors.add(:base, 'Either a Button Press or a Link Click is required, but both are missing.') if button_press.blank? && link_click.blank?
end
private :button_press_or_link_click_presence
end