[not-quite-]vr dev day 3

VR day 3-ish: same day as day 2 but... 3rd iteration. some basic whack-a-mole mock up using qwer/asdf

[not-quite-]vr dev day 2

VR day 2-ish: day 1 + collecting coins. At this rate i'll have something playable in a few years... Most of this is in 1 morning's work through unity tutorial, but I was also playing around with different youtube videos during some bart rides



How to use an older Flash player in Safari

Preventing users from harm is generally a good thing. Preventing developers from harm can be kinda annoying.

While debugging an issue with a Flash based product, I needed to downgrade Flash to the previous version. Downgrading flash itself was a surprisingly straight-forward process. Adobe has a list of its recent Flash updates all listed and downloadable. But once you install it, getting Safari to use it was a different story.

What, you don't use zombocom to check flash installed-ness?
Googling around, I found some solutions that no longer works, involving renaming some directories. But I did find out XProtect is likely what's preventing me from using this older version of Flash, and I ended up at /Library/Internet Plug-Ins/Flash Player.plugin/Contents/. Could editing Info.plist actually trick Safari into thinking this is a newer version of Flash?

I edited CFBundleShortVersionString and CFBundleVersion
It did!

Welcome to zombocom!

Sadly, this didn't help me debug the issue, but by writing this down I'm hoping it helps someone else with a similar problem in the future.


My experience getting started with golang + GAE

I had been itching to try go and finally decided to dive in tonight. The kids are asleep, glass of wine in hand, time to give this a go (no pun intended).

1. Downloading go

I had already done this a while back, but on a typical OS X dev machine, this is a one liner:
$ brew install go

2. Hello world

Martini was the project that pushed me over the edge to play around with go, so I went with their starter project:
package main

import "github.com/go-martini/martini"

func main() {
  m := martini.Classic()
  m.Get("/", func() string {
    return "Hello world!"
Running this worked without any issues:
go get github.com/go-martini/martini
go run server.go
And I had localhost:3000 up and running. Wee!

3. Hosting?

Coming from ruby/javascript background, I was hoping for a free/sandbox PAAS with a simple CLI like Heroku or Nodejitsu, but I wasn't able to find one. To be fair, I didn't really try too hard, but my guess is that with go being a Google project, most people just use Google App Engine. Side note: last time I used GAE, I set up a JRuby server at Tapjoy to fetch Android marketplace data before play.google.com was a thing (The app still exists, but I forgot the actual paths for the real stuff.)

4. Deploying

Getting GAE up and running was a bit more pain than I had hoped for:

1. Installation bash script:
$ curl https://dl.google.com/dl/cloudsdk/release/install_google_cloud_sdk.bash | bash

2. I had to set up a new project and was assigned a project ID of platinum-trees-564 and a git repo. That's nice, I would prefer to use Github but I don't want to muck around too much with the process until I'm comfortable with it, so let's keep going with it. Oh it looks like there is a deploy script built in to the git server? Let's try that.

$ git push
(...blah blah...)
remote: Scanning pack: 100% (3/3), done.
remote: Storing objects: 100% (3/3), done.
remote: Processing commits: 100% (1/1), done.
remote: Starting execution...
=remote: Created deployment: platinum-trees-564.clouddev.gaeTemplate-d981b975f1ecaa6d.deployment_1398662263832
remote: Dispatched
remote: Deployment '[email protected]@[email protected][email protected]' is in PENDING.
remote: Scanning files on local disk.
remote: Uploading 1 files.
remote: Sending batch containing 1 file(s) totaling 0KB.
remote: Cloning 2 application files.
remote: Uploaded 1 files.
remote: Initiating update.
remote: Deploying new version.
remote: Closing update: new version is ready to start serving.
remote: Updated successfully
remote: Deployment to App Engine successful.
To https://source.developers.google.com/p/platinum-trees-564/r/default
   611be7f..7b646ae  master -> master
3. Nope, deploy didn't work. Logs say:
Request failed because the app binary was missing. This can generally be fixed by redeploying your app.
4. From this Go doc I try fixing up the app.yml file. No luck
5. Found this other doc that talks about running the GAE server locally.
goapp serve
Wat. Where did this goapp come from?
6. Going through the logs from step 3.1 (installation script), I find that I installed some things at ~/dev/google-cloud-sdk. It turns out I need to run ~/dev/google-cloud-sdk/platform/google_appengine/goapp. I could probably add this to my path, but it would be nice if this had been mentioned somewhere before.
7. GOTO step 5. Oops, goapp doesn't seem to like martini. This seems to be a problem with martini as it's trying to default to port 3000, and goapp wants it to use 8080. Screw it, let's go with even more barebone helloworld:
package hello
import (

func init() {
    http.HandleFunc("/", handler)

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, "Hello, world!")
8. Success! localhost:8080 is now working. This doc now shows me how to deploy my app:

goapp deploy .
9. Finally, I see the same page on platinum-trees-564.appspot.com.

5. Overall experience

A-minus? It wasn't the smooth Heroku experience I'm used to - but I went 5*-to-60 in under 2 hours, so I would say that's pretty damn good.

* since I already had go installed, and some previous experience with GAE.


Accept my accept-language

I have a pretty simple accept-language setting in Chrome:

Quick check reveals this to be "en-US,ko;q=0.8" and according to the RFC, this is roughly "I prefer American English, but will accept Korean." English has the default quality value of 1, while Korean has 0.8.

But for some reason this is a difficult concept for people:

My guess is either:

  1. the default quality value is being parsed wrong, and English is being assigned q=0 instead of q=1 or
  2. en-US doesn't match en and is being bypassed,
leading the server to believing Korean is my preferred language. To be fair, the RFC does state that "all languages are equally acceptable" but it's still somewhat annoying that my preferred order is being ignored.

Localization is hard.

updated 2014-03-16 18:08:00 UTC

Once I updated the Chrome settings again (with the same order), my accept-language now reads "en-US,en;q=0.8,ko;q=0.6" and everything works "as expected". #2 above was likely the culprit, and at some point between when I last changed language settings and now, Chrome must have fixed this behavior on the header settings.


Twiddla gem

just published a new gem called twiddla, it's a very simple API wrapper for Twiddla.



Your root path should never return an error

The other day I was checking out a link from Hacker News:
HackerNews Reader on Windows Store
This was the first time I had seen a Windows Store link. I had written a crawler about a year ago that would hit up API urls and gather information about Windows Phone 7 marketplace (this probably deserves a write-up by itself), so naturally I was curious. One of my pet peeves is a prominent top-left logo that is not linked. It says "Windows Store", I should be able to click on that and it should take me to a page about the store like Apple, or the store itself like Google.

Failing at that, I decided to just go to the / url, and this is what I got:

When http://subdomain.domain.com/bar has content with human interaction, the root path of that subdomain should never print out vague server error messages like this. There are only two legitimate status codes I should receive: 200 and 301; otherwise, you're doing UX wrong.


CES hilarity

This is insane...ly uncomfortable...ly funny.

Found the video, best part starts around 1:30 mark: http://www.qualcomm.com/ces


"The other people should get a generous severance now"

Interesting read from Reed Hastings on "Netflix Culture". It's somewhat similar to "A players hire other A players, B players hire C players", but pertaining to employee retention.
The Keeper Test Managers Use:
Which of my people, if they told me they were leaving, for a similar job at a peer company, would I fight hard to keep at Netflix? The other people should get a generous severance now, so we can open a slot to try to find a star for that role. (page 25)


2013 goals

fun = %w(lisp emacs)
jvm = %w(clojure scala)
js  = %w(backbone angular ember)
learn fun + jvm.sample(1) + js.sample(1)

kids = %w(alex emily)


read   += 1

write  += 1
code   += 1
health += 1


post-mortem from Rails Rumble

A little background:

I wrote a rails app over the weekend with two friends, as a part of Rails Rumble. I had thought about entering both RR and Node Knockout in the past but this was the first time actually competing. Considering each of us thought we could contribute about 8 hours (but probably did more like 12), it went quite well, and it was a lot of stress-free fun as well.

Deciding on an idea:

ElephantUp was our second choice project. Our first choice was iPhoto replacement with a DropBox like native/web interface, but we scrapped it when we realized:

  1. it wasn't going to get done with 3 people * 8 hours
  2. Amazon S3/Glacier were not allowed in the rules because they are paid services

Another idea was an exchange board for McDonald's Monopoly game pieces, but turns out McDonald's specifically forbids this type of thing.

ElephantUp was essentially a place to collect bookmarks, where you can search for items. Half way through the design process we realized EverNote does something similar though a browser extension, AND their logo is an elephant. Please don't sue us, EverNote.

What went right:

A LOT of this went fairly smoothly actually. None of us really stayed up coding the night away, and a lot of work was done asynchronously with everyone 50 miles from one another.
  • Division of labor: Gerad with his product management background was able to lay out a fairly detailed workflow of things to get done, Bert was able to set up the server quickly and keep things from breaking, and I decided to get more frontend-y. Since all of us were really devs, we outsourced design and layout work to Bootstrap, and got art/icons from free cliparts. Having each team member specialize on a particular technology at the beginning turned out to be a great decision for us.
  • Communication: Bert was in south bay, Gerad in SF, and I live in east bay, so everything had to be online, and we decided to keep things light in terms of communication tools:
  • Flowdock for group chat
  • Google chat for individual chat (though we didn't really use this)
  • Github issues for product/project management
  • Github issues for bug tracking
  • Not re-inventing wheels (well we did try to reinvent bookmarking): No big surprises here, but relying on a lot of third-party tools and libraries helped cut down on development time tremendously. A sample of great products we used:
  • Railswizard - good starting point to get a new rails app going with script templates
  • Bootstrap and Bootswatch - I'm guessing more than half the entries this year are using Bootstrap.
  • HTML2Canvas - we ended up taking screenshots of websites by injecting javascript into the site via bookmarklets. 
  • Thinking Sphinx - for fast indexing of large amount of text
  • And a slew of your standard tools: haml, sass, omniauth, etc.

What went wrong:

Not a whole lot went wrong really, but there definitely were a few things I would do differently.

  • Not testing in Windows: nothing really works in IE8/9, though I'm told it works in IE10. Not a big issue, but we probably should have left a message about that.
  • Not having a link to vote in RailsRumble: nothing huge, but seems like a low-hanging fruit that we missed.
  • Not doing a full QA test until the last minute: we caught a bug with 5 minutes left, and had to do some tag deletion/force-pushes to get it out the door. I think the last deploy happened right at 11:58pm UTC. Having some sort of a "test suite" steps that we performed a few times a day would have ameliorated this.
  • Not having any analytics plugged in: it would have been nice to know when people go and sign up or add links through Google analytics or GoSquared that was offered to teams. We do have airbrake hooked up, so at least we'll get notified when things break...
  • Not doing TDD: probably not a huge deal in a 48-hour hackathon, but there were definitely times where we were re-fixing some methods because another commit changed the return value or something like that. Some basic tests with automated testing would have been helpful.

Overall a very positive experience, and can't wait til Node.js Knockout in November!


delegate with has_many not possible in Rails

Rails delegations give you convenient methods, but it turns out you can't delegate to has_many relations, due to the way Rails implements it. I'm not sure if it's a bug, but essentially, I had a structure like:

In city.rb, I wanted to rewrite the #sub_cities_names method as a delegate, but:

Looking at the source, this makes sense. Anything with "sub_city" just won't work because the relation is "sub_cities," and at that point it returns ActiveRecord::Relation, so I can't do much from there.

edit: this is a little closer, but kinda ugly:


Fork Harder - my first Chrome extension!

Fork Harder brings back "Hardcore Forking Action" to Github. Inspired by this tweet.