Module one final project @ Flatiron School — Trip logging app
For this project, I chose to build a trip logging app. Travelers can create an account, save and delete trips, keep track of them, associate activities with their trips, and write a post about an activity. Travelers can also browse the world with an interactive world map in the terminal, as well as get more info on a country they are curious about. Let’s dive in!
Context
For the Module One final project, we had to build a Command Line CRUD (Create, Read, Update, Delete) App that uses a database to persist information. As it suggests, the user interacts only with the Command Line.
This project emphasizes on the following skills:
- Ruby
- Object Orientation
- Relationships (via ActiveRecord)
- Problem Solving (via creating a Command Line Interface (CLI))
Project set up
Goals:
- Create models and tables with a join table.
- Access a Sqlite3 database using ActiveRecord.
- Define user stories and allow users to interact with the database via the CLI.
- Be aware of Object Oriented design patterns.
My application contains three models: Traveler
, Trip
and Activity
and three tables: travelers
,trips
and activities
.
The relationships between them can be written as follow:
- A traveler has many activities
- A traveler has many trips through activities
- A trip has many activities
- A trip has many travelers through activities
- An activity belongs to a traveler
- An activity belongs to a trip
I created the associations between all the models as follow:
# lib/models/activity.rb
class Activity < ActiveRecord::Base belongs_to :traveller
belongs_to :trip
# lib/models/traveler.rb
class Traveller < ActiveRecord::Base has_many :activities
has_many :trips, through: :activities
# lib/models/trip.rb
class Trip < ActiveRecord::Basehas_many :activities
has_many :travelers, through: :activities
Activities
table is, therefore, the link between Trips
and Travelers
After migrating my tables to the database, we get this schema:
ActiveRecord::Schema.define(version: 2019_03_25_164343) do
create_table "activities", force: :cascade do |t| t.string "activity_name"
t.text "comment"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "traveller_id"
t.integer "trip_id"
end create_table "travellers", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end create_table "trips", force: :cascade do |t|
t.string "city"
t.string "country"
t.string "continent"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
end
Now I have my models and tables, and I also have access to a sqlite3 database thanks to ActiveRecord. It’s nice to have the structure but how am I going to allow my users to interact with the CLI?
The CLI
The CLI is where I define the methods of the CRUD. The CLI is a simple ruby file where I will define the start method which will be called in my Rakefile:
require_relative 'config/environment'
require 'sinatra/activerecord/rake' desc 'Run the app'
task :run do
cli = CLI.new
cli.start
end
Run the app
Quick set up
- Fork and clone my repository
- Run
bundle install
in your terminal to install the dependencies needed. - In order to view the world map in your terminal make sure to install
mapscii
as such:sudo npm install -g mapscii
, if you don’t the app will break. - Run
rake db:seed
to get the database.
Start the app
To start the application: rake run
in your terminal.
Nice!!
Go for TTY !!
For this project, I used TTY-Prompt, a Ruby gem that made my life so much easier to prompt the user in the command line and retrieve its input. Let me give you a quick overview:
I got this beautiful menu using one of tty-prompt methods:
choices = {
'Trips': :trips,
'Activities': :activities,
'Browse the world': :browse,
'Exit Travel Ta Life': :quit
} answer = @prompt.select("What are you up to?", choices)
You can also collect more than one answer using collect
, it looks like this:
def add_trip
puts "Create a new trip below: "
new_trip = @prompt.collect do
key(:city).ask('City?')
key(:country).ask('Country?')
end
Pretty cool right?
Get country facts with the restcountries API
One of the application functionality is that a traveler can enter a country is interested in and get back some pieces of information in the terminal about that country.
For that, I used the restcoutries API (free and no key is necessary):
Browse the world…
If the user selects the option get real
in the Browse the world
menu, he will get the world in his terminal, so cool:
We can zoom in, zoom out, and use arrows keys to explore our world! For that I used mapscii. Check it out, it’s pretty cool.
Last words
It was a great week where I learned so much building this project on my own. I used git and GitHub to commit and push, created new branches every time I was working on a new feature, really I felt like a real developer building this little CLI app!! So much fun! I can’t wait to move forward and build real web app… 🙌