Introduction
This project was created as one of my Flatiron School development course assignments. The purpose of this project was to use the ruby-on-rails framework to create an interactive website backed with a PostgreSQL database. The project also required use of OmniAuth for authentication and retrievable user profiles.
Purpose / Vision
This is a website that allows dog owners to find a dog daycare center, select dates and make reservations, and choose from a range of activities available to entertain the dog during their stay.
Overview
Users create an account with their personal and dog information. Once they create their account and authenticate, users are able to make a reservation on a specific date and select what activities their dog should have during the day. Users submit their selections and receive confirmation. A separate administration section allows an admin user to add locations, dates available, and activities available that users can then select.
Requirements
The following requirements formed the baseline of functionality for the initial release of the project.
- Users must be able to sign-up through a form on the website.
- Users must be able to sign-in through a form on the website using either login credentials or a linked account.
- Users must be able to view their profile and edit it
- Users must be able to add or delete one or more dogs to their account
- Once a user has one or more dogs associated with their account, they must be able to create reservations for any of their dogs.
- When creating a new reservation, a user must be able to add zero to all available activities to the reservation as add-ons.
- When creating a new reservation, a user must be able to add a custom activity to their reservation.
- A user must be able to delete a reservation.
- The website must allow users to view and perform filtering on listed locations and activities.
UX Research
The User Experience Research phase of the project focused on the development of personas, user stories and scenario mapping.
Personas
Several personas were developed of potential users of the website Dog Daycare. A common thread for the personas was dog owners who wanted to use a dog daycare service with the advantages of an online space to schedule and customize their usage.
User Stories
The user stories were informative of the expectations that a typical user would have for the website. The user stories revealed that the website should have lots of options and give dog owners the ability to fit the service to their specific situations.
Scenario Mapping
Was built by focusing on several essential features of the website and how users would approach them. Detailed below is the user discovery process of activities available for dogs at the daycare locations.
UX Design
The UX Design phase built on the UX Research phase and incorporated design into development of functionality that users desired. The color palette aimed for a bright and “earthy” look and feel. The logo and typography aimed to bring a modern and clean design to the website.
Color Palette
The colors chosen are bright and “earthy”. The aim is to evoke a welcoming feel with the bright colors. The earth tones are meant to connect the daycare services to the outdoors and suggest to users that many of the activities will provide dogs with outdoor time and activities.
Logo and Typography
The logo used for the branding is a simple use of the words Dog Daycare and making use of two earth tones from the color palette. There is a vertical version as well, which appears in the footer. The typography used for the logo is Futura PT. Headings and body text is Roboto.
Information Architecture
The structure of the website is not overly complex. It consists of a home page, which is contextual based on a user being logged in or not. An about and contact pages - which are static pages. The activities and locations pages are interactive and allow the user to view activities or locations based on several filters. Finally, the reservations and profile pages are contextual based on the user login.
Development
This website was developed to meet specific requirements including:
- use of the ruby-on-rails web framework
- user authentication with secure passwords
- optional user authentication via OmniAuth
- a relational database back-end and execution of CRUD actions
- web interface that supports filter actions
Database
The database made use of several related tables. The reservation table was set up with associations to users and through the reservations users and dogs were associated with activities.
Classes
There were several classes required of which the User, Dog, and Reservation classes made up the backbone of the application. Within each class - as is standard in ruby development - specific relationship, data validations, scopes, and class methods are stated.
class Activity < ApplicationRecord
has_many :location_activities, dependent: :destroy
has_many :locations, through: :location_activities
has_many :reservation_activities, dependent: :destroy
validates :name, presence: true
validates :description, presence: true
validates :best_for_size, presence: true
validates :best_for_type, presence: true
validates :energy_usage, presence: true
scope :uniq_values, ->(column){ distinct.pluck(column).delete_if{|e| [] << e if e == "custom"}.sort }
scope :all_except_custom, -> { where("custom = ?", false) }
def self.by_select(which_column, value)
where("#{which_column} = ?", value)
end
def self.activity_columns
["best_for_size", "best_for_type", "energy_usage"]
end
def self.top
joins(:reservation_activities).group('activities.id').having('count(activity_id) > ?', 0).order('count(activity_id)').reverse.first
end
end
Controllers
The controllers mediate the actions between the user manipulating the view and the class models and database. A typical controller action is to allow a user to issue a create CRUD action on a database table. In the dog daycare application a user can create a dog and associate it with their user. The controller oversees this transaction.
def create
@dog = Dog.new(dog_params)
if @dog.save
redirect_to user_path(@dog.user), notice: "New dog successfully added to your account"
else
render :new
end
end
Views
Users interact with the application through views. The views employ Embedded Ruby (ERB) to inject ruby code into the view which are rendered and presented to the user. A typical scenario is linking users to different views for editing their user account information. To retain the correct user information when navigating to new views, ERB is used to pass a @user object around from view to view.
<div class="column is-one-third">
<article class='box'>
<h4 class="title is-5">Account Actions</h4>
<p><%= link_to 'Edit Your User Account', edit_user_path(@user) %></p>
<% if @user.addresses.size > 0 %>
<p><%= link_to 'Edit Address Details', edit_user_address_path(@user, @user.addresses.first) %></p>
<% else %>
<p><%= link_to 'Add a New Address', new_user_address_path(@user) %></p>
<% end %>
<p><%= link_to 'Add a New Dog', new_user_dog_path(@user) %></p>
<% if current_user.dogs.size > 0 %>
<p><%= link_to 'Add a New Reservation', new_user_reservation_path(@user) %></p>
<% end %>
<p><%= link_to 'View the Most Popular Activity', activities_top_path %></p>
</article>
</div>
Routing in Ruby on Rails
Routing in Ruby on Rails is built upon the RESTful approach. This allows predictability for the most common types of user interactions. It also allowed the application to prevent user access to particular RESTful actions since Ruby on Rails will prevent routing to unauthorized paths. This was helpful to control how such application information like reservations was accessed and modified. Nested routes allowed reservation content only to be created or edited via a nested user route, otherwise the route would be unauthorized.
# users
resources :users, only: [:index, :show, :new, :create, :edit, :update] do
resources :addresses, only: [:show, :new, :create, :edit, :update]
resources :dogs, only: [:show, :new, :create, :edit, :update]
resources :reservations, only: [:show, :new, :create, :edit, :update]
end
User Interface Styling
The user interface styling was achieved with the Bulma CSS Framework. Bulma was chosen for it’s modern look & feel and modular structure. A particularly interesting component of Bulma for this application was the card component. This component had a polished presentation and was highly customizable.
The ERB code used to create this allowed for dynamic display of the component based on finding associated dogs to a user.
<div class='column is-half'>
<h4 class="title is-4">Dogs</h4>
<% if @dogs.size > 0 %>
<% @dogs.each do |dog| %>
<article class='box'>
<h4 class='title is-5'><%= link_to dog.name, user_dog_path(@user, dog) %></h4>
<%= image_tag('dog_profile.jpg', alt: 'Dog Profile Image', class: 'is-pulled-right user-dog-image') %>
<p><strong>Name:</strong> <%= dog.breed %></p>
<p><strong>Age:</strong> <%= years_old dog %></p>
<p><strong>Sex:</strong> <%= dog.sex %></p>
<p><strong>Number of Reservations:</strong> <%= dog.reservations.size %></p>
<hr>
<p><%= link_to 'Edit Dog Details', edit_user_dog_path(@user, dog) %></p>
<p><%= link_to 'Remove this Dog', dog, method: :delete, data: { confirm: "Are you sure?" } %></p>
</article>
<% end %>
<% else %>
<article class="message is-danger">
<div class="message-body">
No dogs found...
</div>
</article>
<% end %>
</div>
Conclusion
This project was great experience with the Ruby on Rails web framework - making use of important MVC (Model - View - Controller) concepts. The project also allowed me to explore user interface design. Overall, I was pleased with how the project came together to create an interactive website. In further development, I would definitely improve on the reservation user experience - allowing users to select using a calendar object instead of drop-down lists.