在允许first_name或last_name为null但不能同时为null的rails上进行验证

时间:2020-01-11 05:09:55

标签: ruby-on-rails ruby rspec model rspec-rails

class Profile < ApplicationRecord
  belongs_to :user
  validate :first_or_last_name_null


  def first_or_last_name_null
    if first_name.nil? && last_name.nil?
        errors.add(:base, "either first_name or last_name must be present!")
    end
  end

我不知道我的代码行有什么问题,无法从rspec中获取以下错误。 分配rq11验证程序:当姓氏存在时,允许个人资料的名字为空 失败/错误:期望(Profile.new(:first_name => nil,:last_name =>“ Smith”,:gender =>“ male”))。be_valid 预期#<Profile id: nil, gender: "male", birth_year: nil, first_name: nil, last_name: "Smith", user_id: nil, created_at: nil, updated_at: nil>.valid?返回true,得到false

规范文件具有以下..

context "rq11" do
      context "Validators:" do
        it "does not allow a User without a username" do
          expect(User.new(:username=> "")).to_not be_valid
        end

        it "does not allow a Profile with a null first and last name" do
          expect(Profile.new(:first_name=>nil, :last_name=>nil, :gender=>"male")).to_not be_valid
        end
        it "allows a Profile with a null first name when last name present" do
          expect(Profile.new(:first_name=>nil, :last_name=>"Smith", :gender=>"male")).to be_valid
        end
        it "allows a Profile with a null last name when first name present" do
          expect(Profile.new(:first_name=>"Joe", :last_name=>nil, :gender=>"male")).to be_valid
        end

        it "does not allow a Profile with a gender other than male or female " do
          expect(Profile.new(:first_name=>"first", :last_name=>"last", :gender=>"neutral")).to_not be_valid
        end
        it "does not allow a boy named Sue" do
          expect(Profile.new(:first_name=>"Sue", :last_name=>"last", :gender=>"male")).to_not be_valid
        end
        it "allows a Profile with gender male" do
          expect(Profile.new(:first_name=>"first", :last_name=>"last", :gender=>"male")).to be_valid
        end
        it "allows a Profile with gender female" do
          expect(Profile.new(:first_name=>"first", :last_name=>"last", :gender=>"female")).to be_valid
        end
      end
    end

2 个答案:

答案 0 :(得分:3)

我认为这是无效的,因为user_id为空。我记得默认情况下,rails会验证关联的存在。将user_id添加到所有配置文件中,就可以了

答案 1 :(得分:3)

尽管罗曼的答案是正确的,但我想添加更多详细信息和更多选项来解决问题。

您的Profile belong_to :user。默认情况下,belongs_to关联要求关联的对象存在。在这种情况下,必须有一个用户与配置文件相关联,否则该配置文件将无效。

根据您的用例,您可以通过三种方法来解决此问题:

  1. 使关联为可选,请阅读有关optional belongs_to associations in the Rails Guides的信息。如果显然在您的应用程序上下文中有必要不需要关联始终存在,则这只是一个选择。

    belongs_to :user, optional: true
    

    optional: true禁用内置验证。

  2. 您要确保规范中的每个配置文件始终分配有有效的用户。这样的事情可能会起作用:

    let(:user) { User.find_or_create_by(username: 'test_user') }
    
    it "does not allow a Profile with a null first and last name" do
      expect(Profile.new(user: user, first_name: nil, last_name: nil, gender: "male")).to_not be_valid
    end
    
  3. 您不仅会测试实例是否有效,而且还会测试是否存在预期的特定错误

    it "does not allow a Profile with a null first and last name" do
      profile = Profile.new(:first_name=>nil, :last_name=>nil, :gender=>"male")
      profile.valid? # trigger validations
    
      # with all Rails versions
      expect(profile.errors[:base]).to include "either first_name or last_name must be present!"
    
      # or with Rails >= 6:
      expect(profile.errors).to be_of_kind(:base, "either first_name or last_name must be present!")
    end
    
相关问题