Search code examples
ruby-on-railsvalidationruby-on-rails-4.1updatemodel

How do I set up a model validation test on update only if association exists?


How do I set up a test that checks validations only on update if the model has an association? Below are the 2 classes and the test.

user.rb
class User < ActiveRecord::Base
    has_one :survey
    validates :first_name, presence: true, on: :update, if: :survey_completed?

    private
    def survey_completed?
        survey.present?
    end
end

survey.rb
class Survey < ActiveRecord::Base
    belongs_to :user
    validates :user, presence: true
end


user_spec.rb
describe "if survey is completed" do
  let(:user) {User.create(email: '[email protected]')}
  let(:survey) {Survey.create(user_id: user.id)}

  it "returns error if phone number has not been completed" do   
    user.first_name = 'test'
    expect(user.reload.valid?).to be false
  end
end

The above test fails, it returns true. Having looked in the console, I can see that the test is failing because there is no survey for my user, so the validations aren't being run.

I've tried variations with save!, using reload, and not using reload and the test always returns true. How do I set up the test so that there is a survey associated with the user?

For simplicity, I've only shown the relevant code.


Solution

  • In rspec let is lazy. It isn't evaluated until you use the variable in your code. Since your test does not have survey in it, the line let(:survey) {Survey.create(user_id: user.id)} is never run.

    For this test, I would explicitly create a survey on user (i.e. user.survey.create) so the validation will run properly.