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
I don't know what is wrong in my lines of code to get the following error from rspec.. Assignment rq11 Validators: allows a Profile with a null first name when last name present
Failure/Error: expect(Profile.new(:first_name=>nil, :last_name=>"Smith", :gender=>"male")).to be_valid
expected `#<Profile id: nil, gender: "male", birth_year: nil, first_name: nil, last_name: "Smith", user_id: nil, created_at: nil, updated_at: nil>.valid?` to return true, got false
The spec file has the following ..
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
While Roman's answer is correct, I would like to add more details and more options to solve the issue.
Your Profile
belong_to :user
. Per default belongs_to
associations require the associated object to exist. In this case, there must be a user associated with a profile otherwise the profile will not be valid.
You have three options to fix this issue, depending on your use-case:
Make the association optional, read about optional belongs_to
associations in the Rails Guides. This obviously is only an option if it makes sense in the context of your application that there is no need for an association to always exist.
belongs_to :user, optional: true
optional: true
disables the built-in validation.
You make sure that each profile in your spec has always a valid user assigned. Something like this might work:
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
You do not only test if an instance is valid, but instead, if there is an expected, specific error
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