One of my favorite things to do with my family is play MadLibs. We are all grown adults, but we still love it like we were 12-years-old. (Yes, we still use funny words like "smelly" and "dingleberries.") So, for my second project with Flatiron School, which combined Ruby + Sinatra + ActiveRecord, I decided to make a MadLib application where YOU can write some awesome, nerdy MadLibs. I had planned on providing 3-4 stories to choose from, but my focus was coding, not writing. Therefore, I only wrote one story-- A Better Star Wars Holiday Special (because no one liked the original).
It works just like the original MadLibs. I provided a list of fields to fill in-- noun, verb, animal, etc.-- and based the revealed story off the classic poem, "The Night Before Christmas." I tweaked the original poem and added a lot of well-timed blanks, creating such shenanigans as, "When what to my pink eyes did appear, but a miniature First Order TIE Fighter and 5 tiny Wookiee!"
The features I included allow users to:
- create and delete a user account
- validate username, email, and password
- keep the password secure and local
- create, edit, and delete stories
- view all their stories in one place, with time created/updated
- view all stories created by all users, with time created/updated
Having spent the past few weeks learning the behind the scenes components individually, it was a bit challenging when using them all at the same time. You can't just "INSERT INTO html (views, pages) VALUES (dynamic routes, .erb files)". (Sorry-- programming humor.) You have to make sure they can all work together. Learning SQL was very helpful, but how you learned to code it isn't always how you use it. There are gems and helpers and all kinds of applications that do a lot of the hard work for you. One caveat-- you have to learn THEIR languages to utilize them. However, once you get a grip on all those shortcuts, tags, and methods, life really DOES get easier!
My favorite shortcut was using the gem Faker. Faker generates fake data based on what information you need. It was nice to have some real data to seed my database without writing it myself over and over again. The best use of this application comes into play when a user gets tired of coming up with words for the story. If you leave a field blank, Faker will provide an appropriate answer for you. Leave them all blank and watch the madness unfold!
Using Faker, however, also presented me with my biggest challenge. How do I root out the empty/nil values in the user's hash (@starwars) and replace those with the corresponding values from the Faker hash (@faker_hash), without writing over EVERY field? I would have to iterate over both hashes and somehow get their keys to match up, compare the values, and see which values are blank, etc. etc. etc. I tried elaborate methods using "if value.empty?...", some direct SQL, and a bit of voodoo and nothing seemed to work. Enter my cohort leader Jenn and the magic .send method!
.send() is an instance method in Ruby's Object class that allows you to call any method without knowing its name. It uses dynamic dispatching to send a method to an object without being explicit about the method’s contents within our application. It is kind of hard to comprehend until you've either repeatedly used it or noticed it being used in other ways. Jenn is a big fan and encourages us to utilize it more. Since this is my first time using it, bear with me as I try to explain its magic.
In the above example, I have class Starwar with a long hash of Faker data. I needed the .send method because I had an argument-- the @starwars hash, compiled of data entered by the user-- but I didn't know what data would be in there. But I still have to do something with it based on what it turns out to be. If the value of, say, the key named verb_3, is empty, I need to replace it with a fake verb_3 value. But how do you work with what you don't know? I certainly didn't want to perform an "if/else == this" 27 times! In my code snippet above, I created the method, faker_hash, who's only job is defining @faker_hash with a bunch of fake data. In the method fill_in_the_blanks, I used .each to iterate over the values in @faker_hash to get its keys and values. Using the argument of the object key (verb_3) from the method faker_hash, we called the .send method on class Starwar and checked to see if the key of the @starwars hash has a value of empty (" ") or nil. If they are, the .send method is used again to call the setter key= method and set it to the value of faker hash's key.
Confused? I don't blame you. It is hard to operate in this kind of vague work field. I do recommend checking out some more examples of .send and metaprogramming, such as the ones here, here, and here.
I had fun with this project, despite my trepidation towards the beginning of the week. I am feeling more confident about Ruby in general, but have enjoyed getting to use it in relation to websites. Building them was my only experience with coding when I started Flatiron, so its been a relief to get to play in some familiar territory, like HTML and CSS. I hope you decide to give my MadLibs a try!
May the force be with you.