We’ve been celebrating the holidays with a White Elephant gift exchange for many years at Mission Data. This year we still wanted to do a fun company-wide holiday activity while also adhering to social distancing guidelines and safety protocols. We decided on a virtual White Elephant gift exchange (also referred to as Dirty Santy or Yankee Swap), hosted through Zoom. Of course, doing the exchange virtually posed a few challenges, the main one being how to keep track of who has which gift at which time. While keeping track of things such as gift owners and whose turn it currently is could be done on something as mundane as a notepad, we decided to channel our creativity and software expertise into making a web application to help run our White Elephant exchange.
The task of developing the application was given to me, the newest employee at Mission Data, as a fun project that could give me experience with the ground-up development process of a web application without too much pressure or stakes. Since we mostly use Ruby on Rails and React for the backend and frontend accordingly on our projects, it only made sense to use them for this one as well.
Before even writing a single line of code, I had to make sure that I knew the requirements for the application and plan out my development process accordingly. From playing the game before, I knew generally how the application would flow and what logic I would need to code into it. I was also provided with an in-depth description of the game’s rules and what the application was intended to look like, so I could easily base my development around the specifications that were given to me in addition to my prior knowledge of the game itself.
I decided to start with the creation of the models for the application. I knew that at its most simple, the White Elephant game would need two models, one representing a Participant and the other representing a Gift. At first, I thought to keep track of the current owner of each gift in the Participant and Gift models themselves through Active Record Associations. While this approach would have worked, I decided a bit later in my development process that this was not necessary, as I will go over later. Luckily, creating models and setting up the database is seamless in Rails, I simply wrote a new migration which created my corresponding Participant and Gift models, and ran it on the command line.
An example of an ActiveRecord Migration used to create my Participant model:
class CreateParticipants < ActiveRecord::Migration[6.0] def change create_table :participants do |t| t.string :first_name t.string :last_name t.timestamps end end end
With my models now created, I turned to the process of creating the requisite controllers and views for the application. My first reaction when starting this project was to put all the game logic in the Rails controllers and leaving the React component only for the frontend styling. I set up a controller representing the game and also a subsequent view to show the game itself. I wrote a handful of functions to represent stealing a gift, unwrapping a gift, and taking a turn inside the game controller, but once I tackled the React portion of the project, I realized I could do everything in an easier, streamlined way.
Working with React
Before this project, my knowledge of React was very minimal, and as such, I was fairly intimidated by the prospect of working with a completely new framework. However, due to its popularity, React has a wealth of helpful guides that made learning about it especially easy. A huge boon was actually React’s own documentation, which included a guide on making a Tic-Tac-Toe game using React, which contained many useful concepts and pointers that I used while making the White Elephant application.
As I started to create the React portion of the project, I quickly realized that my initial development strategy was wrong. Since every instance of each White Elephant game needed only to be active a short time, there was no point in keeping track of things such as turn player or who currently has which gift in the database models themselves. Rather, all that information could easily be handled using states in React. I simplified my models and controllers, both of which now had nearly nothing within them, and moved nearly all of my game logic into my React components. I decided I could essentially have a React component representing each gift, called GiftTiles, and a React component containing GiftTiles representing a full game of White Elephant. Within these components I could keep track of things such as who has which gift, the turn order, and the number of times that a gift has been stolen in their internal state, greatly simplifying the backend of the application.
Once I realized that I could keep the entire game logic within states in React, making the application functional took a relatively short amount of time. The biggest hurdle was simply learning as I went, and luckily React is pretty easy to pick up. Within several days I had a working prototype of the White Elephant application, and after styling the frontend with Bootstrap, we had a functioning web app available to use for the Mission Data White Elephant gift exchange before Christmas.
This project was a great way for me to familiarize myself with Rails and React, and it showed me the power and simplicity of the React framework. If I were to have done things differently, I would have saved myself a lot of headache by putting all of my application logic in React rather than try to put the logic in the backend, in Rails. Overall, Rails and React provided an easy and relatively painless way to get a functional web application up and running quickly, and I’m looking forward to working with these technologies again soon.