我正在建立一个谱系应用程序,它将采用动物的名字并将其插入到动物模型中。需要鼓励添加动物的父母,但不是必需的。例如,当您回过头谱时,我们会丢失有关谁生成谁的信息。我将父母的名字作为虚拟属性,通过他们的名字而不是模型中的animal_id
搜索其他动物,因为animal_id
没有人会引用其他动物,而是以他们的名字命名。但是,如果有人输入虚假的动物名称,那么我需要将该更新无效。
我的虚拟属性是这样的......
def mother_name=(name)
record = animals.find_by(name: name)
if(record)
self.mother = record
else
self.errors.add(:mother, "does not exist in database. Add her before this animal")
end
end
def mother_name
mother_name
end
当我使用控制台并将母亲的名字改为虚假时,则会正确填充错误属性。当我在对象上执行valid?
时,它会返回true,并且errors.messages
已被刷新。我需要一种方法让它以虚假的方式返回并保持errors.messages
完好无损。
我还添加了一个validates
函数来查看母亲的名字是否在模型中,但是当validates
运行时,我得到一个错误,说nil没有属性叫mother_name
。另外,做两个find_by
似乎有点黑客。
同样,我希望母亲和父亲的名字是可选的,因为我们可能没有父母为前几代人的记录 - 但是如果给出,则需要是正确的。
答案 0 :(得分:2)
我会通过适当的轨道验证来做到这一点,即
class Animal < ApplicationRecord
attr_accessor :mother_name
validate :mother_name_valid
private
def mother_name_valid
mother = Animal.find_by(name: mother_name)
if mother_name.present? && mother.nil?
self.errors.add(:mother_name, "does not exist in database. Add her before this animal")
elsif mother.present?
self.mother = mother
end
end
end
希望这会对你有所帮助。或者你可以写
class Animal < ApplicationRecord
attr_accessor :mother_name
validate :mother_name_valid, if: proc { |animal| animal.mother_name.present? }
private
def mother_name_valid
mother = Animal.find_by(name: mother_name)
if mother.nil?
self.errors.add(:mother_name, "does not exist in database. Add her before this animal")
else
self.mother = mother
end
end
end
if proc
。