controller's before_save methods aren't called in testing

146 Views Asked by At

Following is rails-api only app.

In users_controller.rb

  def sign_up
    @user = User.new(user_params)
    if @user.save
      user = {}
      user[:name] = @user.name
      user[:email] = @user.email
      user[:access_token] = @user.auth_token
      user[:message] = "Successfully Signed up"
      render json: user, status: 200
    else
      render json: @user.errors, status: :unprocessable_entity
    end
  end

  private 
  def user_params
    params.permit(:name, :email, :password, :password_confirmation)
  end

In model/user.rb

attr_accessor :password
before_save :encrypt_password, :generate_token
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true, format: { with: VALID_EMAIL_REGEX } , uniqueness: { case_sensitive:false }
validates :password, :confirmation => true, presence: true, :length => {:within => 6..20}
validates_presence_of :password_salt, :password_hash
validates_presence_of :auth_token

In test/controllers/users_controller_test.rb

test "should create user" do
  assert_difference('User.count') do
    post :sign_up, {email: '[email protected]', name: 'user_3', password: 12345678, password_confirmation: 12345678}
  end
end

user model attributes are:

name email password_hash password_salt auth_token

The test above is failing b'cos @user.errors shows

<ActiveModel::Errors:0x007fd826117140 @base=#<User id: nil, name: "user_3", email: "[email protected]", password_hash: nil, password_salt: nil, auth_token: nil, created_at: nil, updated_at: nil>, @messages={:password_salt=>["can't be blank"], :password_hash=>["can't be blank"], :auth_token=>["can't be blank"]}>

On @user.save before_save :encrypt_password, :generate_token aren't called.

Using gem 'bcrypt' to store the password as hash.

How do I correct this?

1

There are 1 best solutions below

5
On BEST ANSWER

Instead of before_save :encrypt_password, :generate_token use before_validation :encrypt_password, :generate_token. Code in encrypt_password and generate_token is not triggered because you validate model data first and since data is not valid there is no need to trigger before_save because record would not be saved anyway