Rails Project Time, Seeds and Testing
For my final project in rails, I put into practice the more complicated aspects of user authentication and authorization. It’s a simple recipe tracker, but under the hood it is doing some awesome stuff. Watch this video to get an idea of the web application and then read below to understand how it’s built.
Authentication with Devise and Omniauth
The user sign up process is built with Devise, which by default only asks for a user’s email and password. I added a name and a user’s role (like an administrator, moderator or user) to the User table in the database. I also used enum to create user roles in the User model, setting the default to ‘user’ after initializing a new User. This also gives me methods like User.role
and User.admin?
, which returns true if the user is an admin.
I had to modify Devise’s default controllers to allow :name
and :role
in the strong params of the Users::RegistrationsController.
I also needed to modify the views for users to show links to delete comments conditionally, based on their role.
Authorization with Pundit
The Pundit gem sets up simple policies that verify whether a user has a particular role before authorizing them to do that action. So if only administrators and moderators can edit comments the CommentPolicy.rb
looks like:
It is called by simply adding authorize @comment
into comments_controller.rb. I also added a custom rescue for Pundit errors in the ApplicationController.
So if a user tries to do something they shouldn’t be able to do, through some internet wizardry, a notification pops up and says:
Building Seed Data
To work with the web application in my development environment, I built my own seed data using the faker gem. So to create 10 fake users:
Then when I run rake db:seed
I have some users set up to test out permissions with. They’ve got great names too, like Constantin Rath V. I also made seed data for recipes, ingredients and comments.
Writing Tests
My favorite part of this project was learning the importance of testing organically. I was trying to build the various user roles and found myself manually signing up users over and over, trying to test the role function. In a railscast I watched, Ryan Bates mentioned that if you’re testing things in the browser, you should probably write a test for that.
So I used Capybara and Rspec to write a test that signs up a user for each role and then checks if they are signed up in that role. Here’s the test for an admin:
That allowed me to just run the test while I was figuring out the sign up process. When the test passed, I knew it worked without having to manually sign up a new user in all three roles. This is a simple test and I admire the more complex tests used in Test Drive Development. I’ve learned the importance of writing and having quality tests.
In Summation
I learned a lot during this process and did many a first-pump when things started to function as I invisioned them. The biggest lesson I’ve learned from this project is about the importance and practicality of Test Driven Development (TDD). That’s how Learn is built and how I most enjoy writing programs.
Please check out the code on github and comment where you see something you like, or that could be improved.