Ruby on Rails App-Tester

Ruby on Rails (Rails) is a framework for creating simple web applications using the Ruby language. in this post I will walk you through App-Tester, my employee testing app. If you’re interested in the code, you can find it in this Github repository. You are welcome to make any contributions.

Devise Mailer setup

The Getting Started section of Devises README says the next step is, “At this point, a number of instructions will appear in the console. Among these instructions, you’ll need to set up the default URL options for the Devise mailer in each environment. ” To do this, navigate to your config/environments/development.rb file and find the line config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }. If it is commented out, make sure to delete the # at the beginning of the line, and adjust your host and port accordingly. This will allow devise to send emails to the models it generates, if you use an email service that is.


Starting the MVC Structure

The most challenging task for any beginner in Rails (like me) is to structure the Model Views Controller correctly. Specifically in this case, the process of setting up the models. A helpful tool that can ease the structuring process of the Model Views Controller is a cool gem called Devise this is the link to the repo. Devise is designed and created by a large team and is a Ruby gem with the purpose of generating Users and other types of app accounts like Admin. You only need to install the gem by adding gem 'devise' to your gemfile and run bundle install in the terminal. Then, run rails generate devise:install.


Building the ActiveRecord associations

ActiveRecord has built-in macros for setting up object relationships. All you need to do is find the appropriate macros for your project. This application has many different relationships. For example, the client object looks like this:

include DeviseInvitable::Inviter

has_many :applicants, class_name: "User"
has_many :job_posts
has_many :exams, through: :job_posts
has_many :exam_questions, through: :exams

because it has the most control of the other objects. Whereas the Test model is used as a join table, creating an opportunity for a many to many relationship.

class Test < ApplicationRecord
belongs_to :user
belongs_to :exam
has_many :test_answers
accepts_nested_attributes_for :test_answers, :reject_if => :all_blank, :allow_destroy => true

Notice how Test belongs_to both :user and :exam. The User has_many :tests and has_many :exams, through: :tests. At the same time, the Exam has_many :tests and has_many :users, through: :tests. Now that a User and an Exam have the many-many relationship, they can interact with the child models of one another. This allows the User to take a test which gives the user an Exam. With that Exam, the User may also interact with the exam_questions and exam_answers they need to be able to even see the test they are taking. This is achieved by using:

accepts_nested_attributes_for :exam_questions, allow_destroy: true
accepts_nested_attributes_for :exam_answers, allow_destroy: true

Correctly establishing the model relations is the first step to making a fluid application. It is better to spend more time thinking about how you will set up the model relationships before you even start and have a solid plan going into the project than to start the project without a plan and establish relations along the way. A lesson I learned all too well with App-Tester. The plethora of bugs that were caused by improper relations at the beginning led to nearly countless headaches.


Uses Reasonable Validations

Encryption is crucial to protect a companies data. Using Devise to generate both Clients and Users adds password with their DatabaseAuthenticatable module. A description of the module can be found here. Devise also makes use of the module Validatable, which defends against invalid data for emails and password. If an email is unsuccessful in it’s login attempts too many times, the module for Lockable locks the account, making the user validate their account via email to use their account again. Devise is a widely used and versatile addition to any app that uses account validation to access features. The features that I have included which are only accessible to those with accounts are:

  1. The list of Job_posts
  2. The Job_posts corresponding Exams
  3. The ability for Users to take Tests that use the Exams as a building block

Because no “Guest” can access these without signing up, the User and Client models also act as validations for nearly all the data types in App-Tester.


Testing the pages

It is a rule of thumb to start carefully and test each step you do. Otherwise, you will find yourself in a series of unpredictable errors. I started with the application controller, confirming that the view pages work using the resource routes. Because there were multiple nested routes, I had to constantly look at each page when configuring any part of a nested relationships path.

Authenticate with GoogleOauth2

While devise enables excellent user authentication/validation, it is not as secure as Googles profile protections. At the same time, using an already existing Google account is significantly more convenient than filling out a new form. The steps to using omniauth-google-oauth2 can be found here

Clients controller

The Clients controller directory was generated by using the command rails g devise Client. It holds the controllers responsible for implementing the Client registrations, sessions, passwords, unlocks and confirmations. The authenticate method was used to confirm the password with the one being tracked by the password_digest column in the db.

Using Simple_form and partials

Simple_form tags allow us to easily make forms. I made use of the simple_fields_for method to create my nested forms which started with exam and went down the hierarchy of has_many/belongs_to until it went down to exam_answers and exam_questions which required input from the Client to create an exam. This process quickly got complex with the amount of nesting my models had. Because of the complexity of my multi-nested models, I opted for a _form partial. This is a file which has your form on it, but on the pages that use the form, you simply put

<% content_for :page_name, "Submit Your Test" %>

<%= render 'form' %>

This helped avoid a many headaches from needing to make multiple different forms.

Validating your entry fields

You can block the Client from bad entries, such as bad email formatting or leaving one of the fields empty. To do so, you need to use ActiveRecord validations for the entry fields. In the Client class model, I used the validatable shortcut format to authenticate the entry. A shortcut in accomplishing this is using the Devise gem. When a model is generated with rails g devise MODEL it automatically is generated with the validatable module that devise offers.

Conclusion

Rails is basically magic, and as a striving developer, I must practice and learn my craft until I become a wizard. To know how to use ActiveRecord, you need to parse through innumerable documents… Hence, you would learn a huge number of methods that you can add to your wizards tome.


Acknowledging contributing articles

  1. Rails-portfolio-project Github repository
  2. Devise gem this is the link to the repo
  3. Rails quiz blog post by Tressa Sanders
  4. DB browser for sqlite.
  5. RESTful guide table — Railsguide
  6. Validation methods ActiveRecord:Validation