It was almost a year ago when I created an
index.html file in my Atom editor, typed
When I was trying to figure out what to build, I took to heart the wise words of
who told me once to keep it simple, especially when building something for the first time. "Your goal is to learn," he said, "not impress; besides, simple projects done well are impressive for someone at your level."
Given that, I knew I only wanted my app to have a has_many/belongs_to relationship, nothing more. Two models, no join table, no problems. That meant that I would have a User model and something that belongs to User. So I thought a wine journal would lend itself particularly well to this. User
has_many wines, and Wine
belongs_to User. The user would input information about wines they like and store them for future reference. It was perfect!
However, I had a hard time getting excited about the idea, despite my commitment to keep it simple. The idea kept popping into my head to allow all users to view every wine entry, not just their own, and before long I had this concept of a wine-centric social media platform in my head. Once I had named it Vino, there was no turning back.
I knew I wanted to build Vino in a test-driven way, which of course meant I would need to write tests first. The problem with that was I didn't know how to write tests. But I knew how to read tests, and I figured now was as good a time as any to learn how to write them.
I started by mapping out the basic structure of my project. I took out a piece of paper, scribbled out the seven RESTful routes, their corresponding views and what each would contain, and then I had a basic idea of how a user would interact with Vino from log in to log out.
As a former chef, I'm used to learning from people who have come before me. A chef, especially in the early stages of development, researches and uses recipes that they alter to fit their needs. With practice, they start to rely on the recipe less and less. This is similar to the way I decided to learn how to write tests. I searched through repos I had forked on GitHub until I found good examples of RSpec and Capybara tests. I copied them into my spec files, and went through them line by line, rewriting them to suit my expectations for the application. In the end, I had 42 tests in my test suite. They consisted of tests for both models, verifying they had the attributes I wanted them to, and the rest were application controller tests, covering everything from a user being able to log in, to not being able to hack a URL and modify another user's data. Writing the tests was a whole day's work, but I gained in-depth knowledge of how tests work and how to write them, and it made building Vino a much more efficient process.
Once the tests were written, I felt more confident about building, because I was used to running tests and debugging. I started by running the model specs, defining my classes, and writing migrations for the User model and Wine model. Once that was done, it was time to run the application controller specs and define my routes. I really enjoy databases, but when you start defining your routes, that's when you really get to dig in and figure out the logic. That's the stuff I live for when programming, so I really enjoyed debugging my way to a working app.
Pry was my best friend. Since I was building this using Sinatra, I also heavily utilized a gem called Tux, which, when you run
bundle exec tux in your console, opens up an interactive environment that's pretty much like the sexy lovechild of Pry and IRB.
Before long, all my tests were passing, and my data was behaving as it should. My app was working!
Unfortunately, it was also ugly as sin.
I wanted Vino to look nice. It was really important to me that even though I had kept it as basic as I could, that it was something I could be proud of. Something I could point to and say "I did that" without embarrassment. I came pretty damn close to succeeding.
To learn how to do this, I followed a tutorial on w3schools.com that walked me through adding BootstrapCDN scripts and building out a basic grid for a social media-style website. I altered the grid somewhat to suit my needs, and started styling. I thought it would be fun to make it look like Facebook, so I wrote the CSS to make it happen, Googling around whenever I ran into an issue.
It may sound easy, but my first attempt was a miserable failure. Bugs were popping up like crazy as I tried to do things like create cards for each wine entry, and whenever I fixed one bug, another would pop up someplace else. It was like the worst game of Whack-A-Mole I had ever played. I was getting so far down the rabbit hole with my changes, I knew I needed to start over. So I ran
git checkout, started a new branch, and began rebuilding the HTML. After a day or two of work, I had a layout that I liked, and that functioned properly.
git checkout master
git merge revised-layout
When I was as satisfied as I could be with every little detail, I started refactoring the code. I tried to make it as DRY as I could as I started cutting out lines of code that served a purpose in the beginning, but were unnecessary in the finished product. I tried hard not to repeat myself more than necessary. When I was building, all the HTML and CSS for each view was together in each
.erb file. I moved all the CSS to a stylesheet and as much repeated HTML as I could to a layout. It could definitely be more DRY, but I did as much as my lack of experience would allow. With a sigh of relief, I arrived at the moment when I couldn't think of anything else I needed to do. At least for the time being.
git add .
git commit -m "done."
With a smile, I opened a bottle of wine, poured myself a glass, and sat back ...
... then looked at the label, fired up
shotgun, logged in, and put it in my app.
I'd like to add features like comments which would be a good way to incorporate a many to many, or a has_many through relationship. I would like stricter authentication, flash messages, log in with Facebook OAuth, the list goes on. The next thing I want to do is build a Rails app, so I may rebuild Vino in Rails and add these features.
Programming can sometimes be so frustrating I think about doing something else. And then I build something and remember how much I love it. I hope I always find a way to fall back in love with programming.
If you want, you can check out the GitHub repo.