In this project, you’ll be building an exclusive clubhouse where your members can write embarrassing posts about non-members. Inside the clubhouse, members can see who the author of a post is but, outside, they can only see the story and wonder who wrote it.
Disclaimer: This is my implementation of the Members Only project from the Odin Curriculum. I'm not a Rails expert, so do not take this walkthrough as gospel. If you see any errors or something that is incorrect, please feel free to contact me in the comments.
At the end of the project, you should have a simple application that authenticates users to view authors and create posts.
Sign-in page should flash errors if invalid:
Signed-in members can view authors and create new posts:
Change directory to members-only, and generate a User model:
Migrate user model using rake db:migrate command.
Include bcrypt gem in your GemFile and run bundle install command:
Add #has_secure_password to app/models/user.rb file. Can also add additional validations:
Load rails console and create a sample user from command line to verify #has_secure_password method validates password and password_confirmation fields:
In the above example, the password was validated against password_confirmation and saved as a hashed password in the password_digest field.
The#has_secure_password method provides an #authenticate command, which can be used to authenticate user by passing the password as an argument:
##Step 2: Sessions and Sign In
Create a sessions_controller.rb and the corresponding routes.
In config/routes.rb:
In app/controllers/sessions_controller.rb, fill in the #new action to create a blank session and send it to the view.
In app/views/sessions create a new.html.erb file and then create a simple #form_for form to sign-in user:
Now, that users can sign-in, the app should remember when a user is signed-in.
Create a new string column for User table called remember_token. The token will be stored as a cookie and used later to authenticate users.
In the migration file, add the following:
Migrate using rake db:migrate.
When you create a new user, a new token should be created. Use a #before_create callback on the User model to create a new token. Use several helper functions to create random token and then encrypt it. For an explanation of these helper methods, check out Hartl’s Rails tutorial Ch. 8.
In app/controllers/sessions_controller.rb, fill in #create action to create the user’s session.
The above #create action searches for user using submitted e-mail, and then checks if user exists and authenticates using submitted password. If these check out, then it will sign-in user.
The #create action uses a sign_in helper method which you can create in the app/helpers/sessions_helper.rb.
The sign_in method creates a new token and sets cookie equal to new token. Then, the user’s token is updated with hashed token.
(Note: in order to access helper method from controllers, use include statement in app/controllers/application_controller.rb)
Notice the self.current_user = user line above. This statement uses one of the additional helper methods we will create. Again, for a deeper dive into what these methods do, check Hartl’s Rails Tutorial Ch. 8.
##Step 3: Sign out
In app/controllers/sessions_controller.rb, update destroy action:
Most of the functionality is built in the sign_out helper method. After signing out, redirect to your root directory (homepage).
In app/helpers/sessions_helpers.rb', create sign_out` method:
##Step 4: Authentication and Posts
Create a Post model and controller:
After you create model, run rake db:migrate from the command line.
Update routes in config/routes.rb:
(Note: Added a root path that directs to list of posts. As an example, the #sign_out helper method redirects to root path.)
In app/controllers/posts_controller.rb, add before_action method to restrict access to #new and #create actions to only signed-in users:
Create #new action in PostsController:
Create a simple form and save as app/views/posts/new.html.erb:
Now, create #create action in PostsController which automatically updates Posts foreign key (user_id) with the signed-in user. (Note: Need to create a foreign key in the Post model first).
From command line:
Run rake db:migrate and add associations to respective models:
Back to the PostsController, fill in the #create action:
The #create action creates a new post with help from #post_params and also updates post’s foreign key (user_id) with the signed user’s id. Note the usage of #current_user helper function.
Create the #index action to view all posts:
And finally create the corresponding view app/views/posts/index.html.erb:
Using the #signed_in? helper method only allows signed-in users to view authors of each post.
This project did not require registering new users, so from the command line, create several test users, sign-in, and verify that only signed-in users can view authors and create posts.
Lastly, add some custom CSS styling as practice.
Congratulations, you should have a working authentication system similar to the more comprehensive system built in Michael Hartl’s Rails Tutorial.