Skip to content
This repository has been archived by the owner on Jun 8, 2020. It is now read-only.
/ surveyor Public archive

A Ruby on Rails app that collects responses to questions and returns the collected data in an aggregated format

Notifications You must be signed in to change notification settings

aisrael/surveyor

Repository files navigation

Surveyor

This is a Rails project that demonstrates use of rswag to build REST API with autogenerated Swagger or OpenAPI specification.

The Swagger specification is available at /swagger/v1/swagger.yaml.

Usage

Prerequisites

  • Docker (and docker-compose)
  • Ruby 1.6.4+
  • Rails 6.0+
  • Node 12.16+

Development

First clone this repository onto your local workstation:

$ git clone https://github.com/aisrael/surveyor.git
$ cd surveyor

Bring up the test database using docker-compose:

$ docker-compose up -d
Creating network "surveyor_default" with the default driver
Creating surveyor_postgres_1 ... done

Create the test databases:

$ rails db:create db:migrate db:seed
Database 'surveyor_development' already exists
Created database 'surveyor_test'
== 20200401043703 CreateRespondents: migrating ================================
-- create_table(:respondents)
   -> 0.0121s
== 20200401043703 CreateRespondents: migrated (0.0121s) =======================

== 20200401054813 CreateQuestions: migrating ==================================
-- create_table(:questions)
   -> 0.0098s
== 20200401054813 CreateQuestions: migrated (0.0099s) =========================

== 20200401055617 CreateResponses: migrating ==================================
-- create_table(:responses)
   -> 0.0097s
== 20200401055617 CreateResponses: migrated (0.0098s) =========================

Bring up the Rails server:

$ rails server
rails server
=> Booting Puma
=> Rails 6.0.2.2 application starting in development
=> Run `rails server --help` for more startup options
Puma starting in single mode...
* Version 4.3.3 (ruby 2.6.4-p104), codename: Mysterious Traveller
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://127.0.0.1:3000
* Listening on tcp://[::1]:3000
Use Ctrl-C to stop

At this point, you should be able to make requests to http://localhost:3000.

Usage

Submitting Responses

$ curl -X POST http://localhost:3000/api/v1/responses -H 'Content-Type: application/json' -d '{"respondentIdentifier": "00001", "responses": [{"questionId": 1, "body": 4}, {"questionId": 2, "body": "Unclear expectations"}]}'

Should return:

{
  "data": [
    {
      "id": 1,
      "respondentIdentifier": "00001",
      "questionId": 1,
      "body": 4
    },
    {
      "id": 2,
      "respondentIdentifier": "00001",
      "questionId": 2,
      "body": "Unclear expectations"
    }
  ]
}

Trying to submit another set of responses for the same respondentIdentifier gives an error:

$ curl -X POST http://localhost:3000/api/v1/responses -H 'Content-Type: application/json' -d '{"respondentIdentifier": "00001", "responses": [{"questionId": 1, "body": 4}, {"questionId": 2, "body": "Unclear expectations"}]}'
{"errors":[{"status":400,"title":"Respondent already submitted response(s)"}]}

Let's add another set of responses for a different respondent

$ curl -X POST http://localhost:3000/api/v1/responses -H 'Content-Type: application/json' -d '{"respondentIdentifier": "00002", "responses": [{"questionId": 1, "body": 3}, {"questionId": 2, "body": "Noisy workspace"}]}'
{
  "data": [
    {
      "id": 3,
      "respondentIdentifier": "00002",
      "questionId": 1,
      "body": 3
    },
    {
      "id": 4,
      "respondentIdentifier": "00002",
      "questionId": 2,
      "body": "Noisy workspace"
    }
  ]
}

Retrieve all Responses

$ curl http://localhost:3000/api/v1/responses

Should return

{
  "responses": [
    {
      "questionId": 1,
      "body": 4
    },
    {
      "questionId": 2,
      "body": "Unclear expectations"
    },
    {
      "questionId": 1,
      "body": 3
    },
    {
      "questionId": 2,
      "body": "Noisy workspace"
    }
  ]
}

Average Response Scores for all Responses

$ curl http://localhost:3000/api/v1/averages

Should return

{
  "questionAverages": [
    {
      "questionId": 1,
      "averageScore": 3.5
    }
  ]
}

Response Distributions for Scored Questions

$ curl http://localhost:3000/api/v1/scored-question-distributions

Should return

{
  "scored_question_distributions": [
    {
      "questionId": 1,
      "responseFrequencies": [
        {
          "score": 1,
          "frequency": 0
        },
        {
          "score": 2,
          "frequency": 0
        },
        {
          "score": 3,
          "frequency": 1
        },
        {
          "score": 4,
          "frequency": 1
        },
        {
          "score": 5,
          "frequency": 0
        }
      ]
    },
    {
      "questionId": 3,
      "responseFrequencies": [
        {
          "score": 1,
          "frequency": 0
        },
        {
          "score": 2,
          "frequency": 0
        },
        {
          "score": 3,
          "frequency": 0
        },
        {
          "score": 4,
          "frequency": 0
        },
        {
          "score": 5,
          "frequency": 0
        }
      ]
    },
    {
      "questionId": 4,
      "responseFrequencies": [
        {
          "score": 1,
          "frequency": 0
        },
        {
          "score": 2,
          "frequency": 0
        },
        {
          "score": 3,
          "frequency": 0
        },
        {
          "score": 4,
          "frequency": 0
        },
        {
          "score": 5,
          "frequency": 0
        }
      ]
    },
    {
      "questionId": 5,
      "responseFrequencies": [
        {
          "score": 1,
          "frequency": 0
        },
        {
          "score": 2,
          "frequency": 0
        },
        {
          "score": 3,
          "frequency": 0
        },
        {
          "score": 4,
          "frequency": 0
        },
        {
          "score": 5,
          "frequency": 0
        }
      ]
    }
  ]
}

Demographic Breakdown of Average Scores per Scored Question

$ curl http://localhost:3000/api/v1/profile-segment-scores-by-gender

Should return

{
  "profileSegmentScores": [
    {
      "segment": {
        "gender": "Female"
      },
      "questionAverages": [
        {
          "questionId": 1,
          "averageScore": 4
        }
      ]
    },
    {
      "segment": {
        "gender": "Male"
      },
      "questionAverages": [
        {
          "questionId": 1,
          "averageScore": 3
        }
      ]
    }
  ]
}

Using Docker

Building the Docker image

$ docker build -t aisrael/surveyor .
Sending build context to Docker daemon  88.14MB
Step 1/14 : FROM ruby:2.6.4
 ---> 121862ceb25f
.
.
.

Running the Entire Stack using Docker Compose

If you simply want to run the stack without even building anything, aisrael/surveyor is available for download from [Docker Hub]

$ docker-compose -f docker-compose-prod.yml up -d

Don't forget to initialize the database if you haven't done so:

$ rails db:migrate db:seed

About

A Ruby on Rails app that collects responses to questions and returns the collected data in an aggregated format

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published