我有一个有点复杂的Rails模型设置,我会尽量简化它。此设置的目标是能够拥有长寿命的对象(Person
、Pet
),但它们之间的关系每年都会通过TemporalLink
发生变化。基本上,我有这些型号:
class Person < ActiveRecord::Base
include TemporalObj
has_many :pet_links, class_name: "PetOwnerLink"
has_many :pets, through: :pet_links
end
class Pet < ActiveRecord::Base
include TemporalObj
has_many :owner_links, class_name: "PetOwnerLink"
has_many :owners, through: :owner_links
end
class PetOwnerLink < ActiveRecord::Base
include TemporalLink
belongs_to :owner
belongs_to :pet
end
以及这些问题:
module TemporalLink
extend ActiveSupport::Concern
# Everything that extends TemporalLink must have a `year` attribute.
end
module TemporalObj
extend ActiveSupport::Concern
# Everything that extends TemporalObj must have a find_existing() method.
####################
# Here be dragons! #
####################
end
所需的行为是:
创建
TemporalObj
(Pet
,Person
)时:1) 根据某些条件,使用
find_existing()
检查是否存在现有的。2) 如果发现现有的重复项,请不要执行创建,但仍要对关联对象执行必要的创建。(这似乎是棘手的部分。)
3) 如果未找到重复项,请执行创建。
4) [现有魔法已经自动创建了必要的
TemporalLink
对象。]销毁
TemporalObj
:时1) 检查对象是否在一年以上的时间内存在。(这实际上比本例中更简单。)
2) 如果该对象只存在一年,则销毁它和相关的
TemporalLink
s。3) 如果物体存在一年以上,只需摧毁其中一个
TemporalLink
s。
我的问题是,我在许多TemporalObj
上都有唯一性验证,所以当我试图创建新的副本时,在我执行任何around_create
魔术之前,验证都会失败。有没有想过我该如何说服它发挥作用?
您可以(也应该)在这里使用Rails的内置验证。您所描述的是validates_uniqueness_of
,您可以将其范围扩大到包括多个列。
例如:
class TeacherSchedule < ActiveRecord::Base
validates_uniqueness_of :teacher_id, scope: [:semester_id, :class_id]
end
http://apidock.com/rails/ActiveRecord/Validations/ClassMethods/validates_uniqueness_of
针对JacobEvelyn的评论,我就是这么做的。
- 创建了这样的自定义验证
def maintain_uniquenessmatching_thing=thing.find_by(criteria1:self.criteria1,criteria2:self.criteria2)如果matching_thingself.created_at=matching_thing.created_atmatching_thing.delete终止真的end
-
将其添加到我的验证中
validate:maintain_event_uniqueness
-
它奏效了。