所以,我写了这个自定义验证方法:
class MedicalDegree < ActiveRecord::Base
extend Schools
...
validate :validate_awarded_by_based_on_medical_school_table
...
def validate_awarded_by_based_on_medical_school_table
valid_awarded_by_values = MedicalDegree.medical_schools
if valid_awarded_by_values.empty?
error_msg = "the list was empty"
errors.add(:awarded_by, error_msg)
end
unless valid_awarded_by_values.include?(awarded_by)
error_msg = "is not a valid medical school"
errors.add(:awarded_by, error_msg)
errors.add(:awarded_by, valid_awarded_by_values)
end
end
end
使用medical_schools
中Schools
模块中的models/concerns
函数:
module Schools
extend ActiveSupport::Concern
def medical_schools
schools_list = MedicalSchool.all
valid_awarded_by_values = []
schools_list.each do |school|
valid_awarded_by_values << school.name
end
valid_awarded_by_values
end
end
其中MedicalSchool
是模型名称,应引用medical_schools
域表,其中包含所有有效医学院的名称。
在rails控制台中,此方法可以正常工作,验证也是如此 - 但是,在rspec中,似乎除了 schools_list.each
块之外的所有都会运行,就像在我的测试
it "is valid with all attributes filled" do
credential = build(:medical_degree)
credential.valid?
expect(credential).to be_valid
end
Rspec返回错误:
Failure/Error: expect(credential).to be_valid
expected #<MedicalDegree id: nil, degree_type: "Osteopathic", awarded_by: "Midwestern University Arizona College of Osteopath...", date_awarded: "2001-01-28", created_at: nil, updated_at: nil> to be valid, but got errors: Awarded by the list was empty, Awarded by is not a valid medical school, Awarded by []
我无法弄清楚为什么我的代码在任何地方工作但在rspec测试中,以及为什么只有.each块无法执行(因此valid_awarded_by_values
的数组仍为空)。我还尝试将medical_schools方法的代码放在验证方法本身中,但是也无法运行.each
块,并且似乎只运行了相等语句和if/unless
语句。我真的很喜欢帮助弄清楚我的代码是不是问题,或者只是rspec,以及如何解决这个问题!
编辑:
如果数组本身是在medical_schools方法中定义的,例如
,它就可以正常工作schools_list = ['school01','school02','school03'...]
因为它是我之前的自定义验证(然后我不需要迭代块)。当我决定使用域表来代替值并将其用于验证时,整个问题就开始了。
编辑01:
我开始相信运行自定义验证的rspec存在问题。在rails控制台中,我的验证工作完美,但在rspec中,与MedicalSchool
模型相关的任何内容都为空(MedicalSchool.pluck(:name)
返回一个空列表,尽管数据库中有许多条目,如做了我的迭代(我现在看到这不是最好的方法。)
我还被告知,如果我只想检查数据库中的值,我可以使用MedicalSchool.find_by(awarded_by)
- 但尽管我正在测试的值是数据库表中的值,但在rspec中MedicalSchool.find_by
会返回nil
。
答案 0 :(得分:0)
Schools.medical_schools
的结果基于查询MedicalSchool.all
,类似于
SELECT * FROM medical_schools
因此它需要数据存在于数据库中,然后显示对此进行验证。现在,在您的测试期间,可能会发生您没有在数据库中记录任何医学院,然后MedicalDegree
将无效的情况。这就是"Awarded by the list was empty"
消息存在的原因。
您可以创建一所医学院,然后在测试其有效性之前为该学位指定名称。如果您使用FactoryGirl或其他工厂助手,可以使用它来帮助您。
我建议您不要根据名称或其他任意值来关联数据库,因为当需要更新其中一个值时,您也需要更新另一个表。更好的解决方案是medical_school_id
,然后this documentation中描述的belongs_to
关联。这也将使您更容易使用您的工厂库,至少对于您能够编写的工厂女孩来说
factory :medical_degree do
association :medical_school
end
但是,当您只想获取模型的给定字段的列表时,您可以使用.pluck
所述here
MedicalSchools.pluck(:name)