1

In my Rails application I have a model Profile that belongs_to a User as such:

class User < ApplicationRecord
 has_many :profiles
end

class Profile < ApplicationRecord
  belongs_to :user
  
  validates :user_id, presence: true
end

The factory for Profile is as follows:

FactoryBot.define do
  factory :profile do
    sequence(:name) { |n| "Profile #{n}" }
    association :user
  end
end

Now this test in the model tests is failing:

  it 'should have a valid factory' do
    expect(build(:profile)).to be_valid
  end

Here I'm not sure which part is wrong. Is it testing for the presence for user_id. Should the validator be different? OR should I be creating a user before the profile. Which does not seem right as well, since then its a wrong test, because the factory should be doing this.

What am I doing wrong?

4
  • 2
    1) validates :user_id, presence: true is totally unnecessary, belongs do all things 2) in factory you can simply write user instead of association :user Commented Oct 21 at 12:14
  • But I dont get an error in the form if I comment out the validation
    – mrateb
    Commented Oct 21 at 12:45
  • @mrateb what version of rails are you using? belongs_to default association validations were added in Rails 5, so if you are not receiving an error I have to assume you are on < 5 Commented Oct 21 at 13:07
  • if you have only belongs_to :user then when you try to save Profile without user -> you will get error (so additional validation is not required) Commented Oct 21 at 13:24

2 Answers 2

1

The whole shebang.

Your tests should be testing the behavior of your application not your factories.

If you want to sanity test that your factories produce valid records you do that through linting your factories. It's as easy as:

FactoryBot.lint

This step is often incorporated in bootstrapping your test suite.

And also belongs_to adds a validation by default since Rails 5 came out in 2018. Your validation will actually both add an extra message in the errors and break the application in a subtile way as it will fail if the assocatiated record is not yet saved.

1

belongs_to already has a built in validation to check for presence. So your validates :user_id, presence: true is superfluous.

Basically your validation now + belongs_to equates to:

validates :user_id, presence: true
validates :user, presence: true

If you want to disable the built in validation from the belongs_to, you can set the optional: true option.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.