Update! Feel free to read this article, but then check the better way how to handle this.
I was working on authentication system for my recent Rails project. I've decided to use monban gem for it.
I've started with simple integration test for user sign in.
require 'spec_helper' feature 'Sign in as user' do scenario 'with valid login and password' do FactoryGirl.create(:user, username: 'user', password: 'password') visit root_path fill_in 'Meno', with: 'user' fill_in 'Heslo', with: 'password' click_button 'Prihlásiť' expect(current_path).to eq albums_path expect(page).to have_css '.alert-notice', text: 'Prihlásenie bolo úspešné.' expect(page).to have_link 'Odhlásiť', href: session_path end end
And it failed immediately on factory_girl. So I've created factory file.
FactoryGirl.define do factory :user do username 'user' password 'password' end end
I've set up monban and users table.
rails g monban:scaffold rake db:migrate
Created migration to remove email column and add username column.
rails g migration AddUsernameToUsers username vi db/migrate/... rake db:migrate
class AddUsernameToUsers < ActiveRecord::Migration def change remove_column :users, :email add_column :users, :username, :string end end
It was easy until now. But then I started to struggle with monban. There is no method for setting password in
User model. I've spent some time figuring how to overcome it (note to myself: don't code during the night ;). I was able to fix it just other day, but solution was surprisingly easy. I've created
password= method ;).
class User < ActiveRecord::Base def password=(password) self.password_digest = Monban.encrypt_token(password) end end
And it was working!
But I've forgot one thing. To write the test first! Hmm, but I did not know how to test it before, so I've wrote it afterwards.
require 'spec_helper' describe User do it 'responds to username' do expect(User.new).to respond_to :username end describe '#password=' do it 'sets password_digest to Monban password hash' do user = User.new user.password = 'password' expect(Monban.compare_token(user.password_digest, 'password')).to be_true end end end
Then I've just followed errors from integration test and finally user sign in was done!
p.s. When I am thinking about it now, probably last unit test is useless, because I do no plan to use
password= anywhere in application. Anyway it is better to have additional test than no test at all.