Skip to content

experience-exchange-2307/be_experience_exchange

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Experience Exchange (Back-End)

About

Experience Exchange was built with a core focus in mind - that of the ability to share experiences and knowledge with others. Want to learn to knit? Find a nearby knitting buddy who can pass on their years of knowledge! What about musical interest, piano perhaps? Search for your interests, and whether you'd like an in-person or remote buddy, and you're off to the races!

Experience Exchange is built on a Rails backend leveraging microservices, with a React/TypeScript frontend. The app is deployed via Heroku for backend, and Vercel for frontend.


Link to Frontend Repo
Link to Image Microservice Repo

Contributors

Backend

Frontend

Technologies

Primary:

  • Ruby 3.2.2
  • Rails 7.0.8
  • PostgreSQL

Production Gems:

Testing Gems:

Installation/Setup

Cloning and installing dependencies

  • git clone <repo_name>
  • cd <repo_name>
  • bundle install
  • rails db:{drop,create,migrate}

Third Party APIs

Experience Exchange uses two third party APIs - Geoapify for geocoding, and Unsplash for randomized user images. Only Geoapify needs to be setup in the primary repo for geocoding of a user's address.

Follow the Geoapify documentation to get an API key, and place it in the rails credentials file as follows:

  • EDITOR="code --wait" rails credentials:edit
geoapify:
  api_key: <YOUR_CLIENT_ID>

Setting up data

The seed file already contains a small amount of test data that can be initialized with rails db:seed. Alternative data can be added via editing the seed file, or manual creation in the rails console (rails c).

  • Users: first_name, last_name, email (unique), street, city, state, zip, is_remote, about (optional: lat, lon)
    User.create(first_name: "Steve", last_name: "Jobs", email: "steve@gmail.com", street: "1234 Street", city: "Cupertino", state: "CA", zipcode: "12345", lat: "1.12", lon: "1.12", is_remote: "true", about: "I am a very good programmer")

  • Meetings: date, start_time, end_time, purpose
    Meeting.create!(date: "2023-12-15", start_time: "07:30", end_time: "08:00", purpose: "testing")

  • Skills: name, proficiency, user_id
    Skill.create!(name: "Testing", proficiency: 5, user_id: 1)

  • User_Meetings: user_id, meeting_id, is_requestor
    UserMeeting.create!(user_id: 1, meeting_id: 1, is_requestor: true

Testing

There are two options for testing, either the existing test suite, or manual testing with Postman.

For full coverage of testing, the image microservice also needs to be running on port 5000. Please see further setup instructions for the microservice in that repo. Without it running, related tests for image generation will fail, though users will still be created with nil values in their profile_picture.

Endpoints

Fetch a User - GET /api/v1/users/id

Example Response
{
    "data": {
        "id": "13",
        "type": "user",
        "attributes": {
            "first_name": "Steve",
            "last_name": "Jobs",
            "email": "steve@gmail.com",
            "address": {
                "street": "1234 Street",
                "city": "Cupertino",
                "state": "CA",
                "zipcode": "12345"
            },
            "about": "I am a very good programmer",
            "lat": 1.12,
            "lon": 1.12,
            "is_remote": true,
            "skills": [
                {
                    "name": "Apple",
                    "proficiency": 5
                },
                {
                    "name": "Swift",
                    "proficiency": 5
                },
                {
                    "name": "knitting",
                    "proficiency": 3
                }
            ],
            "profile_picture": "some_url.com"
        }
    }
}

Fetch a User's Meetings - GET /api/v1/users/id/meetings

Example Response
{
    "data": [
        {
            "id": "2",
            "type": "user_meeting",
            "attributes": {
                "date": "2023-12-15",
                "start_time": "01:45 PM",
                "end_time": "02:00 PM",
                "is_accepted": null,
                "purpose": "testing",
                "partner_id": 20,
                "is_host": true
            }
        },
        {
            "id": "3",
            "type": "user_meeting",
            "attributes": {
                "date": "2023-12-16",
                "start_time": "08:30 AM",
                "end_time": "09:00 AM",
                "is_accepted": null,
                "purpose": "Learn about something!",
                "partner_id": 147,
                "is_host": true
            }
        }
    ]
}

Fetch a list of Users by skill - GET /api/v1/search_skills Params: query, user_id

Example Response
{
    "data": [
        {
            "id": "13",
            "type": "searched_user",
            "attributes": {
                "first_name": "Steve",
                "last_name": "Jobs",
                "is_remote": true,
                "skills": [
                    {
                        "name": "Apple",
                        "proficiency": 5
                    },
                    {
                        "name": "Swift",
                        "proficiency": 5
                    },
                    {
                        "name": "knitting",
                        "proficiency": 3
                    }
                ],
                "distance": 6650
            }
        }
    ]
}

Add skills to a user - POST /api/v1/add_skills

Expected Request Body
  {
    "user_id": "1",
    "skills": [
      {
        "name": "skiing",
        "proficiency": "1"
      },
      {
        "name": "ping pong",
        "proficiency": "4"
      }
    ]
  }
Example Response
  {
      "data": {
          "id": "1",
          "type": "user",
          "attributes": {
              "first_name": "Nancy",
              "last_name": "Smith",
              "email": "nancy@test.com",
              "address": {
                  "street": "5925 Dublin Blvd Unit B",
                  "city": "Colorado Springs",
                  "state": "Colorado",
                  "zipcode": "80923"
              },
              "about": "A kind soul to share knitting!",
              "lat": 38.9259362930209,
              "lon": -104.7180106940249,
              "is_remote": false,
              "skills": [
                  {
                      "name": "Knitting",
                      "proficiency": 4
                  },
                  {
                      "name": "skiing",
                      "proficiency": 1
                  },
                  {
                      "name": "ping pong",
                      "proficiency": 4
                  }
              ]
          }
      }
  }

Add a meeting between two Users - POST /api/v1/meetings

Expected Request Body
{
  "user_id": "1",
  "partner_id": "2",
  "date": "2023-12-15",
  "start_time": "07:30",
  "end_time": "08:30",
  "purpose": "free form text",
}
Example Response
{
    "data": {
        "id": "33",
        "type": "meeting",
        "attributes": {
            "date": "2023-12-15",
            "start_time": "07:30 AM",
            "end_time": "08:30 AM",
            "is_accepted": null,
            "purpose": "free form text",
            "partner_id": 300
        }
    }
}

Create a new User - POST /api/v1/users

Expected Request Body
{
    "first_name": "Fake",
    "last_name": "User",
    "email": "some_email@gmail.com",
    "street": "1234 Fake Address",
    "city": "Parker",
    "state": "CO",
    "zipcode": "80134",
    "is_remote": "true",
    "about": "I like turtles"
}
Example Response
{
    "data": {
        "id": "1065",
        "type": "user",
        "attributes": {
            "first_name": "Fake",
            "last_name": "User",
            "email": "some_email@gmail.com",
            "address": {
                "street": "1234 Fake Address",
                "city": "Parker",
                "state": "CO",
                "zipcode": "80134"
            },
            "about": "I like turtles",
            "lat": 39.5184514,
            "lon": -104.7612638,
            "is_remote": true,
            "skills": [],
            "profile_picture": "some_url.com"
        }
    }
}

Database Schema

ActiveRecord::Schema[7.0].define(version: 2023_12_08_212901) do
  # These are extensions that must be enabled in order to support this database
  enable_extension "plpgsql"

  create_table "meetings", force: :cascade do |t|
    t.date "date"
    t.boolean "is_accepted"
    t.string "purpose"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.time "start_time"
    t.time "end_time"
  end

  create_table "skills", force: :cascade do |t|
    t.string "name"
    t.integer "proficiency"
    t.bigint "user_id", null: false
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["user_id"], name: "index_skills_on_user_id"
  end

  create_table "user_meetings", force: :cascade do |t|
    t.bigint "user_id", null: false
    t.bigint "meeting_id", null: false
    t.boolean "is_requestor"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["meeting_id"], name: "index_user_meetings_on_meeting_id"
    t.index ["user_id"], name: "index_user_meetings_on_user_id"
  end

  create_table "users", force: :cascade do |t|
    t.string "first_name"
    t.string "last_name"
    t.string "email"
    t.float "lat"
    t.float "lon"
    t.boolean "is_remote"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.string "about"
    t.string "city"
    t.string "state"
    t.string "zipcode"
    t.string "street"
    t.string "profile_picture"
    t.index ["email"], name: "index_users_on_email", unique: true
  end

  add_foreign_key "skills", "users"
  add_foreign_key "user_meetings", "meetings"
  add_foreign_key "user_meetings", "users"
end

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •  

Languages