Hi, I’m Josh Symonds

I blog about Ruby on Rails, coding, and servers

What I Want for Christmas

Reading time less than 1 minute

I’ve been working super hard recently, though not blogging about it, and meanwhile a lot of people have been asking me what I want for the holiday season.

Thus I’m taking a massive departure from the normal, professional tone of this blog and publishing a list of the holiday presents that would just bowl me over with joy. If you know and love me, feel free to buy any item from this list – or multiple ones if you know and love me that much.

If you don’t, then don’t worry about it! I’ll be back soon with real content that will hopefully be both pithy and edifying.

Huey, for Controlling Phillips Hue Lightbulbs

Reading time 2 minutes

I just authored a cool little Gem that allows for automatic discovery of, and control over, the pretty nifty Phillips Hue lightbulbs. I decided to name it Huey, since I love nothing more than cute and silly names. I only spent a few hours tonight hacking it together, so I’m sure there’s a lot of room for improvement, but it works and does everything it’s supposed to and seems fairly fault tolerant; so I thought, why not announce it and fix problems when I wake up tomorrow?

Dynamic Cache Counters in Rails

Reading time 1 minute

I spent a frustrating hour today searching for a way to do dynamic cache counters in Rails.

The problem is best summed up in a use case. I have a model called votes. A vote can be an upvote or a downvote; I set a column called type indicating what it is. Though I call the column type there’s no need for STI here – there’s really only one model, after all. However, it is polymorphic. You can vote up any kind of content on the site. I want to cache the number of upvotes and downvotes separately for that content. Unfortunately, the out-of-the-box Rails counter mechanism doesn’t let you do this. According to the counter_cache documentation, you must either specify true or the name of the column you’re caching under. You’re out of luck if you want to change it dynamically.

This, then, is the solution I came up with to allow dynamic cache counters.

Rails Concerns V: Searchable With Elasticsearch

Reading time 9 minutes

I use the wonderful elasticsearch for my searching needs. I described in previous posts how I use and test elasticsearch in general; but in my current project, I found myself using elasticsearch in a very similar way across all my models. Call me crazy, but that sounds like a concern to me!

As a result of this concern, I ended up having a really neat abstraction that allowed me to search across all my models using elastcisearch’s multi-index search functionality. The end result of this concern was not only less duplicated code; it was a useful utility function that acted on all the models that implemented it.

Rails Concerns IV: Class Methodable

Reading time 2 minutes

In my application, seed data is an unfortunate necessity. I don’t like it but it’s there, and it’s tightly integrated into many parts of the app (dropdowns, navigational links, and so on). Finding that seed data also tends to be rather ugly and long, unfortunately. Who wants to type Tag.find_by_name('Health & Wellness') or one of the finder variations every time you’re looking for something? Not me, that’s for sure. I found myself aliasing these finders constantly as class methods: so, the above would be much more easily referenced as Tag.health_wellness.

Once I started duplicating this functionality across models I knew I had a concern. This is the module I came up with to encapsulate it.

Unobtrusive JavaScript Facebook-Style More Button

Reading time 2 minutes

I spent awhile yesterday Googling for a Facebook-style more button with a graceful fallback: something where, if the user didn’t have JavaScript, they’d still see something sensible… but if they did, they’d get a sweet fade-in of more content appended right to the content container. Oh, and I also didn’t want to write separate views for JSON returns, so it had to deal with HTML returns and strip out the unnecessary bits.

I didn’t find anything, so I took a crack at creating it myself. This is the result.

Seamless POST Logins With Rack Middleware

Reading time 6 minutes

It’s not uncommon to have login-required forms accessible to users who aren’t logged in – for example, maybe you’re trying to encourage someone to start writing some content without having to bother logging in first. Of course, they have to log in before they can post, but what happens when they push that big “post” button? Or take another example: you have a button to thumbs-up some content. Only logged-in users should be able to thumbs-up any content, but you always want to display the button. But then what happens when someone who’s not logged in presses the button? In most Rails applications, they’d be logged in, redirected back to the page they were referred from, and they’d have to click the thumbs-up again.

That sort of sucks. They already clicked it once. Why can’t we remember that?

I ran into this problem myself today in the context of the thumbs-up button. After doing some research and realizing there was no great Rails 3 solution to the problem, I decided I would roll one myself. The result is some complicated but awesome Rack middleware that I think would be pretty handy for most Rails developers.

Kinotify, a RubyMotion App

Reading time 1 minute

Today, I’d like to announce the official release of my first RubyMotion app – Kinotify! Kinotify is a simple app with a lofty goal: to notify you of the release of upcoming movies, either in theaters or on DVD. You can search for movies – in case you have something you really want to be notified of in the future, say a rerelease of Dirty Dancing or the future release of Avatar II – or just see all upcoming releases. Notifications you set will arrive at 2PM local time on your phone, and you can set the app to remind you of a release a month, week, three days, and/or one day in advance.

The UI, icon, and website were all designed by my good friend and super-talented dude Luke Beard, so they all look totally awesome. And on the flipside, the Rails server and RubyMotion app were all done by yours truly… so any faults (and I’m sure there are some I haven’t found) are mine and mine alone.

It was a long road to actually releasing this app. I started designing Kinotify with a good friend of mine (who had the original idea and inspiration for the application) way back in March, so it’s been months of labor, testing, asset acquisition, releasing and refining and coding. But I think the results speak for themselves: Kinotify is a pretty awesome application, and even better I think it’s a great example of what RubyMotion is capable of. It uses remote notifications, core data, Twitter/Facebook sharing, networking and reachability… and thanks to RubyMotion it was all pretty painless to get it working together.

This week I’ll make another blog post describing what took so long, where my time and energy were spent, and the general process of releasing a RubyMotion app on the iTunes store. But I just got the approval email from Apple so I wanted to unleash Kinotify on the world officially. So what are you waiting for? It’s only 99 cents! Go get Kinotify already!

And if you have any problems or want new features, the best way to contact me is on Twitter. Thanks!

Introduction to Programming III

Reading time 10 minutes

Another in the exciting introduction to programming series! This is looking like it’ll be a four-part series; at least, I think I’m running into a wall in terms of complexity that I think defines the end of “introduction.” Still, I hope it’ll be helpful to someone, and it’ll hopefully be a popular class at the Center on Halsted.

Dynamic Error Pages, Corrected

Reading time 3 minutes

Earlier today @alan_meier pointed out that in certain circumstances, my post on dynamic error pages leads to unexpected results: namely, though most errors are caught, 404s are not. I didn’t experience this myself because most 404s, for me, result in an ActiveRecord::RecordNotFound error, since my application has a wildcard route at the very end. But if you don’t then my post on dynamic error pages won’t work for you very well. Here, then, is an explanation of the problem and how to fix it.