Halloween season came around and with it came big bags of candy at the office. Some candies disappeared faster than others, leading exclamations like “aww all the Twix are gone!” or “there’s nothing but stupid 3 Musketeers left” to be heard around the office. Summer remarked that we needed an app to tell us how best to divide the candy so that no one who didn’t want stupid 3 Musketeers would be forced to eat them, and the weirdos who actually like 3 Musketeers could revel in their abundance. Enter my next pet project.
I knew I needed a database to keep track of all the candy, plus let users give their candy preferences. I went with a Rails app since I knew it would be fastest for me to get going, since I’m most familiar with Rails as a platform for basic CRUD apps. I basically wanted to make an app that would let a group of people see each other’s candy opinions, as well as let individuals rate each candy. I wanted the rating process to be fun, and I had the idea for a range of smiley faces as indicators of how much you liked a candy.
I figured I’d deploy to Heroku because I always deploy to Heroku, again because it’s the fastest, most convenient option when deploying my own little apps. So I went ahead and set up the app with a PostgreSQL database since that works well on Heroku. I hadn’t fiddled with PostgreSQL on my MacBook since upgrading to El Capitan, but it wasn’t hard using Homebrew.
The first thing was figuring out my data model, which is one of my favorite parts of any new project that involves a database. I knew I wanted accounts, so I got going with Devise for authentication, which necessitated a users table. I customized Devise a bit, going with a username field instead of email because I wanted a single login for my whole office to use, and I wanted it to match that of an app David built for us.
This deviation from the Devise default of using an email address actually led to a bug because of an oversight on my part. Steve helpfully caught the bug which allowed a user to register a new account with a blank password, but then you couldn’t log back in after you’d logged out. This happened because I couldn’t use
devise :validatablein my User model because that validates that the email is provided when signing up, but it also validates a password is given. So I had to manually add some password validation logic to the User model, along with validation for my custom username field that replaced the email field.
I added a candies table and tied each candy to a user account. I did this thinking some non-American might try the app someday and not give a hoot about our silly American candies, or they might think that Smarties are some chocolate candy made by Nestlé instead of those powdery things found in the US. So each user account gets their own set of candies, though I do have users by default get a predefined selection of American candies for them to rate.
There’s a people table and each user account can have many people. This is how I have a single account for my office and all my coworkers are included in it. I went with something simple like this because I knew strict access control wasn’t a concern. It works on the honor system, each person only setting their own preferences. If you were using the app with your rambunctious children, you might have a problem where one child sets the other’s preferences for him so as to ensure their brother gets all the terrible candies, for example. This hasn’t been a problem at my office… yet.
The preferences table ties a person to a candy with a rating of like, love, hate, or dislike. If you are indifferent towards a candy, you just don’t have a preference table entry at all for it. Summer proposed distinguishing between indifference and just not having rated a candy yet, and I agree it would be helpful. I’d like to show a list, for example, of which candies people have not yet rated.
The major feature of the app was to tell the user how to divide their hypothetical trick-or-treat bag of candy in a way that pleases everyone. I did this by adding a few scopes to my Candy model:
- All candies that are only liked or loved by a single person. I display these all listed together with the suggestion that they all be given to that one person:
- All candies that are liked or loved by multiple people. If the candies are all liked or all loved, I suggest they be split evenly among the people. If the reviews are mixed, though, with one or more people loving the candy while the remainder like it, I suggest they all get some of the candy, but whoever loves the candy should get a bit more. Nick made the suggestion that pickier eaters — those who have more dislikes and hates than likes and loves — should be favored when distributing candy, which I’m considering.
- Candies that have been rated, but that no one likes or loves. The app suggests you throw these in the trash. 😝
Another fun part of the app is the Trends page. It lists the most popular, least popular, and most divisive candies. At our office, the most popular candies include Kit Kat, Sour Patch Kids, and Reese’s Cups. I’m a bit surprised by a sour gummy candy beating out tried-and-true chocolate, but there you are. The most unpopular candies include Circus Peanuts (of course), Necco Wafers, and Milk Duds (???).
The divisive candies are fun because they’re candies that are rated favorably and unfavorably by the same number of people. These include Laffy Taffy, Hershey’s Kisses, and Jolly Ranchers. Jolly Ranchers seem innocuous enough, but anyone actually liking Laffy Taffy kind of confuses me. That stuff will rip your teeth out!
Finally, I tried a new gem with Candyfair: wikipedia-client. I wanted to add photos of each candy, especially since Jon pointed out he didn’t know what some of the candies even were. I was faced with the conundrum that users could add their own candies, and I didn’t want to host a bunch of images or make the user enter image URLs. The Wikipedia gem let me add both a photo and a brief blurb about each candy, as pulled from the Wikipedia API:
There were a couple of hurdles: not every candy has its own Wikipedia page, most notably individual Little Debbie cakes, and not every candy can be found on a page of the same name on Wikipedia. So I added two extra fields to the candies table:
skip_wikipedia. When you visit a candy’s page on Candyfair, it makes an AJAX request to my Rails app which uses the gem to hit up Wikipedia for a page for that candy. If
wikipedia_titleis set, it will search for that, otherwise, it searches for the candy’s name. If
skip_wikipediais set, no AJAX request is ever made and no Wikipedia info is shown.
So that’s Candyfair, a fun little app I built between October 27 and November 3, so just a little over a week. The source code is all on Github and it’s deployed on Heroku if you want to try it out. Pull requests accepted, if you want to contribute!
I saw the little Windows 10 logo show up in my taskbar some few weeks ago, telling me I could reserve a copy of Windows 10 for free. Cool! I did so and waited with excitement for July 29 to come around. It came and went, and my reserved upgrade still wasn’t ready. I saw articles, privacy concerns, Tweets, and a whole subreddit come about, and I felt like the last person who wanted to upgrade but hadn’t yet.
I’ve been replaying Okami HD recently; coming back to it after several years of not playing made me notice anew all the little details that make the game so great. I really recommend the game on PS3, and I hope they rerelease it on the PS4 or make a proper sequel. I found the game originally because I enjoyed The Legend of Zelda: Twilight Princess and saw Okami listed as being a similar game, at least in so far as you got to play as a wolf. I would say now I prefer Okami to Twilight Princess.
I love working out ActiveRecord and Arel queries in Rails apps. I thought I’d share some of the more fun queries I’ve designed in Arel, spread out over a few blog posts. We’ll start with one for fetching tags separated by account.
Jon got me The Witcher 3 as a gift on Steam shortly after it came out because I was replaying Dragon Age 2, again, and he wanted me to find a new game I might love. He had been watching Destiny stream it and thought it looked up my alley. I had heard of the game and had seen it getting rave reviews on Reddit, but I was dubious since it forces you to play as a set character. I’ve not had much luck getting into games like Tomb Raider, Uncharted, and even the first game in the Witcher series; I prefer games like Dragon Age or Skyrim that let you create your own character. However, the bits of The Witcher 3 gameplay I’d seen looked cool, and it’s a super pretty game, so I tried it. I’m so glad I gave it a chance.
My latest project is Steamy Screenshots (view source). It’s an app I made to extract colors from the screenshots people share on Steam. There’s no real usefulness to it, it was just a fun thing to do. You can look up a particular Steam user and view their newest fifty screenshots, or look at the newest screenshots shared for a particular game.