Skip to content

Latest commit

 

History

History
488 lines (440 loc) · 13.8 KB

README.md

File metadata and controls

488 lines (440 loc) · 13.8 KB


rails-badge ruby-badge build-badge closed-pr-badge

This GraphQL on Rails API serves queries and mutations to Tomo, an application that allows language learners to schedule anonymous language exchange sessions without the hassles of coordinating a specific date and time.

Live endpoint: https://tomo-api.herokuapp.com/graphql

Stack: Rails, GraphQL, RSpec, Travis CI, Heroku

Readme Content

Local Setup

Prerequisites:

  • Ruby 3.0.1
  • Rails 6.1

Install gems and setup database:

  • Install gems:

    • bundle (if this fails, try to bundle update and then retry)
  • Setup database:

    • rails db:create
    • rails db:migrate
    • rails db:seed
  • To run your own development server:

Test Suite

  • Run with bundle exec rspec
  • All tests should be passing
  • To view specific test coverage: open coverage/index.html

GraphQL Queries and Mutations

Availabilities

  • Get Availabilities: fetch all availabilities for a user by id

    • Type: Availability

    • Arguments:

      argument :user_id, ID, required: true
      argument :status, String, required: false
      
    • Example request
      {
        getAvailabilities(userId: "1") {
          id
          userId
          status
        }
      }
      

  • Create Availability: create new availability slot for a user with default status of 'open'

    • Type: Availability

    • Arguments:

      argument :user_id, ID, required: true
      argument :start_date_time, Integer, required: true
      argument :end_date_time, Integer, required: true
      argument :status, Integer, required: false
      
    • Example request
      mutation {
        createAvailability(input: { params: {
          userId: "2",
          startDateTime: 1609493400,
          endDateTime: 1609504200
        }}) {
          id
          userId
          startDateTime
          endDateTime
          status
        }
      }
      

  • Update Availability: fetch information for a user by id

    • Type: Availability

    • Arguments:

      argument :id, ID, required: true
      argument :start_date_time, Integer, required: false
      argument :end_date_time, Integer, required: false
      argument :status, Integer, required: false
      
    • status: "1": 'fulfilled', status: "2": 'open'

    • Example request
      mutation {
        updateAvailability(input: { 
            id: "2", 
            startDateTime: 1612324800, 
            endDateTime: 1612328400, 
            status: 1
        }) {
          id
          userId
          startDateTime
          endDateTime
          status
        }
      }
      

Blocked Pairings

  • Create Blocked Pairing: create a new blocked pairing for a user
    • Type: Blocked Pairing

    • Arguments:

      argument :blocking_user_id, ID, required: true
      argument :blocked_user_id, ID, required: true
      
    • Example request
      mutation {
        createBlockedPairing(input: { params: {
          blockingUserId: "1",
          blockedUserId: "2"
        }}) {
          id
          blockingUserId
          blockedUserId
        }
      }
      

Languages

  • Get Languages: get all languages currently supported by the application
    • Type: Language

    • Example request
      {
        getLanguages {
          id
          name
        }
      }
      

Pairings

  • Get Pairings: fetch all pairings for a user by id

    • Type: Pairing

    • Argument:

      argument :user_id, ID, required: true
      
    • Example request
      {
        getPairings(userId: "1") {
          id
          user1Id
          user2Id
          cancelled
        }
      }
      

  • Cancel Pairing: fetch all pairings for a user by id

    • Type: Pairing

    • Argument:

      argument :id, ID, required: true
      argument :user_id, ID, required: true
      
    • Example request
      mutation {
        cancelPairing(input: { id: "4", userId: "1" }) {
          id
          user1Id
          user2Id
          user1Cancelled
          user2Cancelled
          cancelled
      

Topics

  • Get Topic and Translations: returns a random topic and any requested translations for 2 languages by language_id
    • Type: Topic

    • Argument:

      argument :language_ids, [ID], required: true
      
    • Example request
      {
        getTopicAndTranslations(languageIds: ["1", "2"]) {
          id
          description
          translations {
            translation
          }
        }
      }
      

User Languages

  • Create User Language: add a new language for a user
    • Type: Blocked Pairing

    • Arguments:

      argument :user_id, ID, required: true
      argument :language_id, ID, required: true
      argument :fluency_level, Integer, required: true
      
    • fluency_level: 0: 'native', fluency_level: 1: 'target'

    • Example request
      mutation {
        createUserLanguage(input: { params: {
          userId: 1,
          languageId: 1,
          fluencyLevel: 1
        }}) {
          id
          userId
          languageId
          fluencyLevel
        }
      }
      

Users

  • Get User: fetch information for a user by id

    • Type: User

    • Argument:

      argument :id, ID, required: true
      
    • Example request
      {
        getUser(id: "1") {
          id
          username
          email
          availabilities {
            id
          }
          userLanguages {
              id
          }
        }
      }
      

  • Authenticate: get a user based on an authentic email/password

    • Type: User

    • Argument:

      argument :email, STRING, required: true
      argument :password, STRING, required: true
      
    • Example request
      {
        authenticate(email: "[email protected]", password: "1234") {
          id
          username
          email
        }
      }
      

  • Create User: sign up a new user

    • Type: User

    • Arguments:

      argument :email, String, required: true
      argument :username, String, required: true
      argument :password, String, required: true
      argument :password_confirmation, String, required: true
      
    • Example request
      ```
      mutation {
        createUser(input: { params: {
          email: "[email protected]", 
          username: "user", 
          password: "1234", 
          passwordConfirmation: "1234" }
        }) {
          id
          username
          email
        }
      }
      ```
      

  • Update User: update an existing user

    • Type: User

    • Arguments:

      argument :id, Integer, required: true
      argument :email, String, required: false
      argument :username, String, required: false
      argument :target_language_id, String, required: false
      argument :native_language_id, String, required: false
      
    • Example request
      ```
      mutation {
        updateUser(input: {id: 1, username: "person", email: "[email protected]", targetLanguageId: "2", nativeLanguageId: "1"}) {
          id
          username
          email
          userLanguages {
            id
            userId
            languageId
            fluencyLevel
          }
        }
      }
      ```
      

Types

  • Availability

      field :id, ID, null: false
      field :user_id, ID, null: false
      field :start_date_time, String, null: false
      field :end_date_time, String, null: false
      field :status, String, null: false
      field :created_at, String, null: false
      field :updated_at, String, null: false
    
  • Blocked Pairing

      field :id, ID, null: false
      field :blocking_user_id, ID, null: false
      field :blocked_user_id, ID, null: false
      field :created_at, GraphQL::Types::ISO8601DateTime, null: false
      field :updated_at, GraphQL::Types::ISO8601DateTime, null: false
    
  • Language

      field :id, ID, null: false
      field :name, String, null: false
      field :created_at, GraphQL::Types::ISO8601DateTime, null: false
      field :updated_at, GraphQL::Types::ISO8601DateTime, null: false
    
  • Pairing

      field :id, ID, null: false
      field :user1_id, ID, null: false
      field :user2_id, ID, null: false
      field :date_time, Integer, null: false
      field :user1_cancelled, Boolean, null: false
      field :user2_cancelled, Boolean, null: false
      field :cancelled, Boolean, null: false
      field :created_at, GraphQL::Types::ISO8601DateTime, null: false
      field :updated_at, GraphQL::Types::ISO8601DateTime, null: false
    
  • Topic Translation

      field :id, ID, null: false
      field :language_id, ID, null: false
      field :topic_id, ID, null: false
      field :translation, String, null: false
      field :created_at, GraphQL::Types::ISO8601DateTime, null: false
      field :updated_at, GraphQL::Types::ISO8601DateTime, null: false
    
  • Topic

      field :id, ID, null: false
      field :description, String, null: false
      field :translations, [Types::TopicTranslationType], null: true
      field :created_at, GraphQL::Types::ISO8601DateTime, null: false
      field :updated_at, GraphQL::Types::ISO8601DateTime, null: false
    
  • User Language

      field :id, ID, null: false
      field :user_id, ID, null: false
      field :language_id, ID, null: false
      field :fluency_level, String, null: false
      field :created_at, String, null: false
      field :updated_at, String, null: false
    
  • User

      field :id, ID, null: false
      field :username, String, null: false
      field :email, String, null: false
      field :created_at, GraphQL::Types::ISO8601DateTime, null: false
      field :updated_at, GraphQL::Types::ISO8601DateTime, null: false
      field :availabilities, [Types::AvailabilityType], null: false
      field :user_languages, [Types::UserLanguageType], null: false
    

Database Schema

schema

Tables:

  • Users: users that have signed up for the application
  • Availabilities: user's time slots of open availability for pairing
  • Pairings: language exchange sessions that have been scheduled
  • Blocked Pairings: when a user does not wish no pair with another again, they can add that user to their blocked pairings
  • Languages: languages currently supported by the application
  • User Languages: languages that a user has chosen as either their native or target learning language
  • Topics: conversation topics
  • Topic Translations: translation of each conversation topic to supported languages

FAQs

Technical

  • How are pairings created?
    • User A submits an availability block and a new record in Availbilities table is created with default status of 'open'.
    • Backend searches for another availbility with the following parameters:
      • overlapping date and time
      • availability status = open
      • this availability's user is:
        • studying User A's native language
        • speaks language that User A is studying
        • not on User A's blocked pairing list
        • hasn't blocked User A
    • If above criteria is met, a new pairing record is created at the beginning of the overlap time block.
      • Each user's availbility's status is changed to 'fulfilled'.
    • Note: this is an interim solution. The eventual goal is a more direct scheduling experience (like scheduling a meeting).

Project Board

GitHub project