0

I'm having issues with getting Rspec to run my after_create hook.

My User model:

class User < ActiveRecord::Base
  devise :database_authenticatable, :registerable, :recoverable, :rememberable,
         :trackable, :validatable, :confirmable

  has_one :user_profile

  after_create :create_user_profile

  protected

  def create_user_profile
    self.user_profile = UserProfile.new(user: self)
    self.user_profile.save
  end
end

My UserProfile model:

class UserProfile < ActiveRecord::Base
  belongs_to :user

  has_attached_file :avatar,
    styles: { medium: "300x300>", thumb: "100x100>" },
    default_url: "/images/:style/missing.png"
  validates_attachment :avatar,
    content_type: { content_type: "image/jpeg" }
end

My spec:

require 'rails_helper'

RSpec.describe UserProfile, :type => :model do
  describe 'initial create' do
    before do
      @user = User.new(email: '[email protected]',
                       password: 's3kr3t',
                       password_confirmation: 's3kr3t')
      @user.save
    end

    it 'should have profile' do
      expect(@user.user_profile).to be_valid
    end
  end
end

Fails with error:

Failures:                                                                                                                              │~
                                                                                                                                       │~
  1) UserProfile initial create should have profile                                                                                    │~
     Failure/Error: expect(@user.user_profile).to be_valid                                                                             │~
     NoMethodError:                                                                                                                    │~
       undefined method `valid?' for nil:NilClass                                                                                      │~
     # ./spec/models/user_profile_spec.rb:16:in `block (3 levels) in <top (required)>'                                                 │~

2 Answers 2

1

You could do something like this:

RSpec.describe UserProfile, :type => :model do
  describe 'initial create' do
    let(:user) { User.new(email: '[email protected]',
                       password: 's3kr3t',
                       password_confirmation: 's3kr3t') }

    it 'should have profile' do
      @user.save
      expect(@user.user_profile).to_not be_nil
    end

    it "shouldn't have valid profile if not saved" do
      expect(@user.user_profile).to be_nil
    end
  end
end
Sign up to request clarification or add additional context in comments.

3 Comments

RSpec will dynamically match any predicate method (ending in ?). You can see this from OP's error message, where it is failing when trying to call valid?
very interesting @zetetic - I wasn't aware. Is this new behavior?
No, it has done that for a while. RSpec is the Rails of testing frameworks: lots of features to discover.
0

It turns out the given code had multiple errors, most of which had to do with an invalid User model:

  1. Devise expects a password to be 8 chars minimum (so my User model wasn't saved due to its invalidity).
  2. I missed adding the 3 "confirmable" fields to the User model migration.
  3. After migrating my User model, I needed to add a "confirmed_at" attribute to the instantiated User model.
  4. My UserProfile model was also missing a "user_id" attribute in its migration.

Once I fixed these issues, the code worked as expected.

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.