The aim of post is to create only the User Sign Up Page through TDD cycle of creating User Resource, Controller, Model and View.
The User
Model will be very simple having only:
- Email - required, update is disabled once it is created.
- Password - required, should be greater or equal than 8 characters.
- Full Name - required, just for human readable displaying of the user name instead of email.
Note:
The first intention of this blog post was full User authentication, but since it uses TDD step-by-step development, and there is a lot from creating Route, Controller, Model and View this post will be only creating Sign Up page. Second and maybe third post will have validation, saving, authenticating and updating user!
Generate User Integration Test
First we will start with generating Rails integration_test
residing in spec/requests
folder:
1 2 3 |
|
First we will remove a GET /users
as describe
block generated by default in spec/requests/users_spec.rb
and left simple as:
1 2 3 4 |
|
Create User Test
In the users_spec.rb
we will add a context
block that will call the new
route and
expect to have fields for email
, password
, password_confirmation
, full_name
and button Sign Up
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
There are quite few asserts in this test, that is certainly not good practice in testing, but to make this post shorter, it is like this!
TDD Step 1: Routing (Resource)
After running RSpec test or viewing from Guard
the expected error on saving file should be:
1 2 3 4 5 |
|
The problem is that there is no users route created.
Open config/routes.rb
, remove all commented code and add users
resource:
1 2 3 |
|
After run command to examine Rails routes:
1 2 3 4 5 6 7 8 |
|
You will see the new_user
path, but to actually get the path it is needed to be called
with _path
added to the route name as we called it in first test visit new_user_path
.
For this simple authentication we will only need creating and updating of user account, but in future, we may need, a full administration of users, including listing all and destroy them as well!
Guard Routing Error
If there is a LoadError
after applying the route in Guard terminal:
1
|
|
Create a spec/routing
folder, to fix the issue:
1
|
|
After applying the user route (and Guard fix), there is a expected message complaining for existence of users controller.
TDD Step 2: Controller
To make test green, we need to create a user controller and the action or method called new
in the app/controllors/users_controller.rb
:
1 2 3 4 5 |
|
We are creating a new User
and setting it to a instance variable @user
, so it will be
visible within the View page!
The RSpec test will be failing since it doesn’t know what the User
is:
1 2 3 4 |
|
TDD Step 3: Model
To make test green, we need to create a User
model in app/models
and it will have
email
, passmord_digest
and full_name
.
Having a password_digest
field is important as it’s the default name that’s used with Rails
has_secure_password
feature and we’ll be using this feature later.
Use this command to generate User:
1 2 3 4 5 6 7 8 |
|
Change the generate attr_accessible
to include email
, password
, password_confirmation
and full_name
needed for user create and edit form:
1 2 3 4 5 |
|
We also added has_secure_password
to the User model. This was introduced in Rails 3.1
and adds some simple authentication support to the model using that password_digest
column.
Note:
To have this
bcrypt-ruby
gem must be inGemfile
(we included it in first post) as this gem handles hashing the password before its stored in the database.
The generator will create a Model, Migration, RSpec test and a Factory Girl factory since we use it instead default Rails fixtures!
We will have another error regarding database:
1 2 3 4 |
|
Migration
To have a database and make green our test, run command:
1 2 3 4 5 |
|
Note:
This migration will create
development.sqlite3
SQLite 3 database indb
folder andusers
table.
We also need to prepare database for testing with:
1
|
|
Note:
This migration will create
test.sqlite3
SQLite 3 database indb
folder, andusers
table.
The RSpec test still will be failing with complaint on not having a view for user:
1 2 3 4 5 |
|
TDD Step 4: View
As we noted in first tutorial, instead of default Template View Engine erb
, we will use
far more better haml
View Engine.
Converting the erb layout to haml
But before using the haml
View Engine we need to convert default layout generated with
application:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
to much more readable haml
default layout for application:
1 2 3 4 5 6 7 8 9 10 |
|
New User View page
We need to create a view for user called new
, and it needs to have a fields for email
,
full_name
, password
, confirm password
and Sign Up
button.
Create a app/views/users/new.html.haml
:
1 2 3 |
|
User Form Partial
Since the creating and updating User form will be identical, we shall create a partial
to reuse
user form on create and update views:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
And finally the test will be green, ignore for now that spec/models/user_spec.rb
is currently pending!
Testing Sign Up Page with Browser
The beauty of it all, is that we didn’t even start browser, so we can do it now for test by running Rails server (Thin):
1 2 3 4 5 6 7 8 |
|
Open page:
http://localhost:3000/users/new
The design it is not really attractive at all, but it was not scope of the post, and should not be while creating application. When designers create full design it can be applied very easily. Functionality matters for now!
Creating the SignUp route
The /users/new
route name is descriptive but having just /signup
, I think is far more
better route name!
SignUp Route Test
Create a new test context in spec/resources/users_spec.rb
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
|
The GET /signup
context is added that is now visiting the signup_path
!
Test fails:
1 2 3 4 |
|
There is no signup_path
so we need to create it in routes
:
1 2 3 4 |
|
The test passes and it is green, you can now try testing it in browser:
localhost:3000/signup
It should work just fine!
Conclusion
This post intended to absorb whole authentication of user, but currently is just too long and I will stop here and in second post will introduce validation, saving and maybe yet in third post authenticating and updating user!
Code
The code is hosted on GitHub and can be cloned from the xajler/just-todo-it.
Github xajler/just-todo-it commit for this post: