Skip to content

stevengov/survey_tool

Repository files navigation

Survey Tool

This is a simple survey tool built with Ruby on Rails. It allows users to create surveys with a single yes/no question, respond to surveys, and view the results of the surveys.

Home

Requirements

  • Ruby 3.2
  • Rails 7.1.2
  • SQLite

Getting Started

These instructions will get you a copy of the project up and running on your local machine for development and testing purposes.

Prerequisites

You need to have Ruby 3.2 and Rails 7.1.2 installed on your machine. You can check your version with:

ruby -v
rails -v

If you don't have Ruby and Rails installed, you can follow this guide.

Installation

A step by step series of examples that tell you how to get a development environment running.

  1. Clone the repo
  2. Install dependencies
bundle install
  1. Database creation
rails db:create
  1. Database initialization
rails db:migrate
  1. Database seeding (optional)
rails db:seed
  1. Run the Rails app
rails s
  1. Navigate to localhost:3000 or localhost:3000/surveys on your browser. You should see the following

Testing

To run tests, run the following

RAILS_ENV=test bin/rails db:migrate
rails test

All tests should run and thus giving the following output

# Running:

...........

Finished in 0.621563s, 40.2212 runs/s, 122.2724 assertions/s.
25 runs, 76 assertions, 0 failures, 0 errors, 0 skips

Features

demo.mov

Survey Tool has the following features

Please use Rails to build a simple survey tool, with the following requirements:
- A user should be able to create any number of surveys
- A survey consists of one question represented as a single string. The answer to the question is always Yes or No.
- The home screen of your app should show a list of surveys and a button to create a new one
- A user can respond to a survey by clicking into it from the list mentioned above
- A survey can be answered multiple times with a yes/no response
- You should keep track of when each of the survey responses are saved 
- You should display the results of the survey on the home screen with the percentage of yes and no responses.
Creating a new `survey`
create_survey.mov
Responding to a `survey`
create_response.mov
Showing `responses` of a `survey`
show.mov

Future

Authentication

As the instructions for this assignment states

You don't need to worry about user authentication but you may stub this out if you wish

One solution is to use the Devise gem, a popular authentication solution for Rails. This will handle user registration, login/logout, password resets, and more.

The following section will contain details on how I would create my own user authentication.

User Table

We would create a users table that has a email: string and password_digest: string and password_confirmation: string

User Registration

We would create a controller that handles displaying a registration form. We need endpoints for index, new, and create

Additionally, Rails has a has_secure_password method where we can handle password encryptions. We will use that and define that in the User model.

class UsersController < ApplicationController
  skip_before_action :authenticate_user, only: [:new, :create]

  def index
    @users = User.all
  end

  def new
    @user = User.new
  end

  def create
    @user = User.new(user_params)

    if @user.save
      flash[:notice] = "User created successfully"
      redirect_to users_path
    else
      flash[:alert] = "User not created"
      render :new, status: :unprocessable_entity
    end
  end

  private

  def user_params
    params.require(:user).permit(:name, :password)
  end
end

User Sessions

We also need to manage the session so that we can keep track of the users that are logged-in. We need endpoints for new, create, and destroy

class UserSessionsController < ApplicationController
  skip_before_action :authenticate_user, only: [:new, :create]

  def new
    @user = User.new
  end

  def create
    @user = User.find_by(name: user_params[:name])

    if @user && @user.authenticate(user_params[:password])
      session[:user_id] = @user.id
      redirect_to users_path
    else
      flash[:alert] = "Login failed"
      redirect_to new_user_session_path
    end
  end

  def destroy
    session[:user_id] = nil
    redirect_to root_path 
  end

  private

  def user_params
    params.require(:user).permit(:name, :password)
  end
end

Authentication Controller

We should only allow authenticated users to hit endpoints. To do this, we can define a AuthenticatedController or just simply do this in the ApplicationController. This controller will handle authenticating the user.

Here's a basic authentication function

def authenticate_user
  unless current_user
    render json: { message: 'Unauthorized' }, status: :unauthorized
  end
end

def current_user
  @current_user ||= User.find_by(id: session[:user_id])
end

For views, we can do the following instead

def authenticate_user
  unless current_user
    flash[:alert] = 'Unauthorized. Please log in'
    redirect_to login_path
  end
end

def current_user
  @current_user ||= User.find_by(id: session[:user_id])
end

From there, we can add it to each of the controllers! Essentially, we need this

append_before_action :authenticate_user

New Database schema

With the creation of the a new users table, we can add some new associations

  • A user has many surveys, which means a survey belongs to a user
  • A user has many responses to surveys, which means a response belongs to a user

We can add some uniqueness validations throughout the app

  • A user can only create a survey with a unique name.
  • A user can only respond to a survey once

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published