When we started programming EventFindr, we didn’t have much of a roadmap. We knew we wanted to search for live entertainment events using the TicketMaster Discovery API and we knew we wanted to allow the user to choose different parameters for their search. We had some ideas about which parameters we wanted to include, artist name, venue name, date, genre, but we weren’t sure yet which parameters the data from our API would include -- so we started poking around!
The TM API allows queries to a few different tables, but the three we decided we needed were attractions (artists, sports teams, etc.), venues, and events. Events was our join table since an attraction has many events and venues have many events. Luckily, we discovered that instead of simply referring to foreign keys of venues and attractions, the TM API embedded attraction and venue table entries in the return value of the event query! This enabled quick and easy access to all of the data we needed without making multiple queries.
So with our data in hand, we proceeded to write a method to query the API, parse the data, and iterate over its contents. But we needed a way to hide our API key! So we sequestered the key in a global variable in a special file all by itself and added that file to our “.gitignore” file. With the api key safe and local, we were finally able to query the API. The data we needed was sometimes nested up to nine(!) levels deep, but we eventually got all the specific data we needed.
Once we had our nested hash figured out, we pivoted to working on our database migrations -- we populated our three tables with all of the attributes we thought were necessary. Attractions have a name and a genre; venues have a name, address, and city (for ease of search); and events have venue/attraction ids (foreign keys), name, date, time, and url.
With our database set up, we could move on to populating our methods! We wanted at least four use cases, so we looked at the data available and came up with four types of searches: by city and date, by performer and city, “what tickets go onsale soon near me?”, and “pick and event for me to attend tonight!”. By city and date accommodates users looking for something to do on a specific date, by performer and city helps those looking for when their favorite artist plays in their town, when tickets go onsale is for those savvy concertgoers who buy early to get great seats, and the random event tonight is for those indecisive users looking for something to do that night. With our four use cases, we started designing the methods.
During this process, we discovered that not all of the data purported by the TicketMaster API to be present was actually there! We started getting NoMethodErrors from our iterating methods, the source of which was missing data. Of course there is no method available for keys that don’t exist! To remedy this, we taught ourselves how to use the rescue method -- that way, if we got a NoMethodError, we could handle the exception and substitute new code in place of our iterators. Variables previously set by the iterator were simply populated with placeholder messages like “no genre listed,” and “no time listed”. This enabled us to keep control of the flow of our program in the event of incomplete data.
Now that our methods were retrieving all of the correct data (present or not), we started instantiating Ruby objects based on those data -- easily enough completed, but we ran into another problem. Even though our has_many and belongs_to relationships were populated in our models, our objects weren’t associating with one another. To make matters worse, we were getting duplicate venue objects. There isn’t more than one Moore Theatre, for example, but here we were with multiple ruby objects for one theatre. The solution to this was very easy and belies what a rookie mistake we were making: we hadn’t set any relationships in our object-creation iterator! So we created a helper method that set the relationships using ActiveRecord’s handy association setter methods (event.venue = VenueObject1, event.attraction = AttractionObject1 and so forth). Finally! Our API query, object creation, database migrations, models, and methods were working in conjunction to give us the results we wanted.
Our interface is a very simple CLI, but it gets the job done. The menus loop appropriately, incorrect menu selections return a “please try again” message, and we can’t find any API query that breaks our methods (yet. Never will, fingers crossed).
If I were able to spend more time with this, I would find some gems to jazz up the appearance, come up with some more methods for more use cases, and perhaps even query the attraction and venue APIs directly to allow user searches by things like genre.
I learned a lot doing this first project! I’m really looking forward to learning libraries like React so I can move from CLI interfaces to something more modern and functional. But this was a fun first step!
EventFindr is a simple CLI used to find live entertainment events.
Run 'bundle install' to install required gems.
Create a file named 'api_key.rb' in the 'config' folder. Obtain an api key from ticketmaster here. Once api key is obtained, assign the key to the global variable '$key' as a string in the 'api_key.rb' file.
Run 'rake db:migrate' in the root directory to create the database locally.
Contributions are welcome. Feel free to open a pull request or branch from this project.