Creating A Command Line CRUD App

Hello, world! For my first project as a student web developer at Flatiron School, I partnered with Ge Tian to develop a command-line interface CRUD app. We called it “Twogether: A Project Collaboration App.” In short, it facilitates teamwork among users who want to collaborate on common projects. Check out a quick demo below:

Through creating this project, we became acquainted with tools such as Active Record, ORM, SQLite3, Rake, TTY::Prompt, REST Client and JSON. What follows is a walkthrough of our process!

PHASE 1: THE SET UP

Ge and I brainstormed on a couple of ideas; and with the help of our Flatiron coach, Ethan, we decided on creating a project collaboration app. We planned out our domain models (Project, Task, User, Ownership, Collaboration) and determined the relationships between them:

  • A project has many tasks and has many collaborations, and a project has many users through collaborations
  • A project has one ownership, and has one user who is the owner through the ownership
  • A task belongs to one project, and a task belongs to one user
  • A user has many collaborations, and a user has many projects through these collaborations
  • A user also has many tasks
  • An ownership belongs to one user and one project
  • A collaboration belongs to one user and one project

The Collaboration class is the link between the users and projects many-to-many relationship. Likewise, the Ownership class is the link between a user and a project one-to-many relationship, where a user may be an owner of multiple projects, but a project has only one owner.

We made a list of user stories and their corresponding CRUD actions:

  • As a user, you can log in to your existing account (read) or register for a new account with a username and a password (create)
  • As a user, you can view your current projects (read)
  • As a user, you can view all tasks under a project sorted by due dates (read)
  • As a user, you can add a task to the project (create)
  • As a user, you can edit a task (update)
  • As a user, you can update a due date of a task (update)
  • As a user, you can update the task’s completion status (update)
  • As a user, you can view collaborators on the project, ordered by username alphabetically (read)
  • As a user, you can stop collaborating on a project (delete)
  • As a user, you can create a new project (this will give you ownership of the project) (create)
  • As a user who is an owner of a project, you can edit your project’s name (update), edit your project’s description (update), see the project’s collaborators (read), add a collaborator to your project (update), and delete your project if you so choose (delete)
  • As a user, you can also choose to collaborate on an existing project (update)
  • As a user, you can change your username and your password (update)
  • As a user, you can delete your account (delete)

Phew. Yes, we sure are an ambitious duo.

Next, we set up our environment to ensure we have appropriate files and directories. Most notably, we ensured that we had the following in our Gemfile:

list of gems in gemfile

To break these down a bit for any newcomer: “activerecord” is the Ruby gem (or software package) required for us to implement Active Record, which allows us to use objects and to persist (or store) our data. SQLite3 is the database engine we used in order to execute SQL queries; it doesn’t require network access, making it a stand-alone DBMS (database management system). In addition we use TTY::Prompt, which grants us the ability to easily prompt for user inputs, which is essential for the user to interact with our application. In addition, REST Client and JSON gems allow us to work with APIs; in our case, to add a feature which generates a random quote when the user runs the app.

PHASE 2: SCAFFOLDING

Next, we created classes for our models, ensuring that 1) each model inherits from ActiveRecord::Base and 2) their relationships with other models are specified. For example:

We then created our database and migrations, employing Rake (which gives us ready-made commands for common tasks) features such as rake db:migrate (to migrate our created tables) and rake db:seed to seed our data.

An Example of A Migration
Auto-generated schema.rb file after migration
A snippet of our seeds data in seeds.rb

PHASE 3: EXECUTION

We used an ASCII arts generator to add some pizzazz to our app. We created log-in and register features that allow the user to either log in or a create a new account; we ensured that validation checks are there for given passwords and usernames. We added a random inspirational quote feature to the page to give users a bite-size piece of motivation to get them started on their work.

We created a main menu that lets users navigate among several project options, as well as administrative ones.

A user can view current projects by selecting the first option and then upon choosing a project they are a part of, they are taken to the project menu. From here, they can 1) view all the tasks that are part of that project, 2) view/update their tasks (by marking task as completed, editing task description, or changing the due date), 3) add a new task, 4) see all their fellow collaborators, 5) choose to stop the collaboration (given that they are not the creator of the project).

In addition, a user has the choice to create a brand new project.

We created a page to let users manage the projects they created via the following options:

Administratively, the user can change their username and password:

They can also delete their account:

As far as the tools that we used to bring to life all the features above, we employed largely TTY::Prompt to prompt for and receive user inputs. We performed CRUD tasks via methods provided by Active Record. For example, here is a sample snippet of code that handles our log-in functionality.

We used User.find_by(username: username_input, password: password_input) to search for the user in the database

We wrote these methods in a separate class called Interface. We tackled one user story at a time, and tested each method as we went. There were some challenges and of course, bugs, along the way. One of which was in prompting the user for the due date upon them creating a task and then validating that they had entered a date format that we can work with. This required us to learn some basics about Regular Expressions and Date and Time Ruby classes. We were able to successfully validate the user’s date input in the following way:

Some things we definitely could have done differently include housekeeping work such as maintaining more DRY code and separating our methods into different classes (presently, the Interface model houses the majority of our methods). In addition, we could have explored further Active Record functions beyond the basics to avoid such repetitions as the below:

Overall, creating this project was as challenging as it was rewarding! We are so excited to take what we have learned, build even more knowledge on top of it, and bring to life more creations in the future!

dev | i like to create things | linkedin.com/in/vuonganht/