Ruby on Rails Project

Kameron Hungerford
7 min readDec 31, 2020

The Rails project was an exciting project. The Sinatra project we completed prior definitely helped build a foundation for this project. Sinatra taught me the basics of routes and the MVC framework. Moving onto Rails I was able to understand what was happening behind the scenes when using generators and other shortcuts provided in Rails.

Choosing a topic for this project was pretty easy. I love animals so it was a no-brainer that I choose a topic that had to do with animals. Initially I chose to create an application to manage a zoo and the animals and zookeepers within that zoo. The zoo idea did not work like I wanted to. I had trouble deciding what models were needed and how they were related. I knew I wanted to do something with animals, so I chose something simpler. I chose to create a veterinarian application that would allow a user to manage a collection of animals and their appointments.

I began by creating my migrations with the help of Rails generators. From there I established the belongs_to relationships of my models within the migrations. This would automatically create some of the foreign keys in the appropriate tables. For password security, I made sure to include my bycrpt gem in my Gemfile and the password_digest column in the users table. This would work with the has_secure_password macro that is used in the User model. Together these salt and hash the users password so it is not stored as plain text in the database. After I created the migrations I started to create my models. I needed a User, Animal, Appointment, Veterinarian, and a Service model. After the models were created, I defined all of my necessary relationships such as has_many, belongs_to, and has_many through. Defining the model relationships is always the trickiest part for me. To make sure these relationships were correctly established I used the Rails console to call specific methods on instances of my model classes. It took me a good while to make sure these were setup correctly. After I managed to correctly set up the relationships, things went pretty smoothly.

After creating the models and establishing their relationships, I moved onto the routes. I started out with very basic routes using the resources keyword. The resources keyword automatically creates routes for all of the necessary CRUD actions. I will later define specific routes needed for certain pages such as login or signup.

After I created my routes, I was able to move onto the controllers. In each controller I created the necessary CRUD actions to complete a Rails application. These were just the basic actions which had not yet contained any logic. I also created an additional controller for my sessions. This controller helps with the login and authentication process. I then tested each of the actions within the controllers to make sure I hit each route correctly. After checking to make sure the I was hitting the appropriate action for each controller I could then create my views.

I started with basic views that contained plain text to make sure my routes were taking me to the appropriate action and view. After I tested each view I was then able to begin working on the logic for each action in the controllers. The controller I started with was the users controller. I wanted to make sure I had a secure and properly implemented signup. I began within the new action in the users controller. I created an instance variable that would act as a dummy instance so the view would have something to work with. The new action worked, so I moved onto the create action which would create a new user. I started by creating a form in the new.html.erb file. A user needed a name, email, and a password. From here I created the logic of creating a new user which included strong params, which would permit certain params from my form. I checked my params with Pry to make sure everything was working correctly. After adding the logic of creating a new instance of a user, I made sure no invalid data was being saved to the database by added a few more lines of logic. If the user was correctly saved to the database then they would be redirected to the user show page, otherwise the signup form would be re-rendered. After I created the logic for the signup process, I could move onto the show action logic. This is always a simple action and the only logic need was to find a particular user by their id. The only other action I wanted in my users controller was the destroy action which would allow a user to delete their account.

After I had the users controller fully setup, I moved onto the sessions controller which would authenticate a current user and login them into their account. Using the find_by and authenticate methods I was able to create logic to find a user and check to see if they entered the correct password. If the user was found and the password was correct, the user id would be set in the sessions hash and the user would be redirected to the their show page. If the information was incorrect then the login form would be re-rendered. The only other action I created for the sessions controller at the time was the destroy action which would clear the session and log the user out.

In the application controller I defined methods for current_user and require_login which would set the current user of the session so that a user could not access other users information. The require_login method was set to prevent anyone who was not logged in being able to access all of the information. These methods were then used across all of the controllers to add some security to my application.

Creating all of the other controllers were pretty simple. They all pretty much contained the same logic with some minor tweaks depending on the usage of the model. The controllers for animals and appointments I wanted full CRUD action so that a user could create, read, update, and destroy their animals and appointments. I did not want any random user to be able to add new veterinarians and services as this would make things pretty messy. The only CRUD actions I wanted for veterinarians and services was create but only by an admin user.

I started to create the ability to create an admin account by adding a new column with the datatype of boolean to the users table. I was able to do this with the help of a migration and I set the default value of the column to false because I did not want all accounts to be admins. I added a checkbox to the signup form to give the ability to create an admin account. An admin account would, for example, be for a secretary at a veterinarians office. The admin would be able to add new veterinarians and new services if the office were to hire a new veterinarian or offer a new service. The admin user would also be able to update and destroy all animals and appointments in the database. This was achieved with the help of a helper method I defined in the application controller called admin? If the current_user.admin == true then the current_user would be set under the helper method admin? I then used the admin? method in the views to define what an admin and a regular user could see.

As I mentioned above, I started with very basic routes using the resources keyword but the requirements of the project required more than just that. I had to create specific routes for my login and signup pages so it would follow standard conventions of RESTful routing. I also created a couple of nested routes so that a user could navigate to routes such as users/:id/animals/:id/appointments and users/:id/animals/new. It was very simple to implement. The path helpers for these routes really come in handy when creating links.

The next piece of functionality I added was the ability to login with a Google account. This part was pretty difficult at first but I was able to work out the bugs pretty quickly. With the help of the omniauth and omniauth-google-oauth2 gems I was able to add this feature. I had to navigate to the Google developers page to get my client id and secret. To use this feature I had to create an omniauth.rb file in config/initializers and define my provider for omniauth to use. In a seperate file called .env I set the client id and the secret. After creating that file I then added .env to the .gitingnore file so that not just anyone could access this secure information on my github repository. I then created a new action called create_with_google so that a user could be correctly logged in and a random password was generated for that user. I used the SecureRandom.hex method to generate this random secure password.

The last thing I did was code and design the rest of my views. I was able to achieve a lot of this with the help of embedded Ruby and ActionView helpers such as link_to and image_tag. These automatically write the HTML code for you so you don’t have to write it all out yourself. After I my had views set up the way I wanted them I did quite a bit of CSS styling. I went back and forth with many different styles and designs until I was pleased with the end results. I ended up with a pretty simplistic and minimalistic design. Some times less is more. I am genuinely proud of what I have achieved within this project!

--

--