OnyxRaven

OnyxRaven's Blog

‘Octopress!’

So I moved everything over to Octopress/Jekyll – I really like being able to write pretty normal markdown as the syntax for everything. Most of the generator code is just ruby, and the template engine is Liquid (which is kinda weird but whatever).

I’m still tweaking the styling. I found a good starting point for using the Solarized colorscheme, but its got some kinda strange bugs that are a little tough to get out.

Rails REST API Versioning

There have been a few other articles regarding versioning REST APIs in Rails. Many reference this RailsCasts (#350) to set up header based versioning, and there have been a few setting up path based versioning using the ‘namespace’ feature in Rails 3 routing.

Our API was set up with path based using routing namespaces, and we moved ahead happily with v1.

1
2
3
4
5
6
namespace :v1 do
  resource :ping
end

class Api::V1::PingController ...
end
1
GET http://example.org/v1/ping

Recently we started working on v2 features, and started in a new namespace, looking just like v1. To make it easy on our apps, we wanted to make all the API calls against the v2 api, even on controllers that didn’t get an ‘upgrade’ into the v2 namespace.

1
2
3
http://example.org/v1/ping
http://example.org/v2/ping #fallback to the v1
http://example.org/v2/pong #use v2 namespace

This is a non-obvious operation. In most REST cases, redirects like explained in this StackOverflow post are not possible because you shouldn’t redirect POSTs (technically an HTTP 301 response should work, but there are few HTTP clients that respect that strict mode. If you don’t believe a 301 response to a POST should result in a new POST, read the spec carefully).

Josh Symonds talks about how existing API solutions are terrible, and really only one of the gems Symonds talks about in his post handles ‘fallback’ apis: rocket_pants. I wasn’t keen on using the whole kit of rocket_pants features, so I looked into how the ‘api’ method works. Its just a fancy wrapper around a ‘scope’ line.

Taking a cue from that, I came up with the replacement for the ‘namespace’ lines:

1
2
3
4
5
6
7
scope :module => 'v2', :path => ':api_version', :constraints => { :api_version => /v2/ } do
   resource :pong
end

scope :module => 'v1', :path => ':api_version', :constraints => { :api_version => /v[12]/ } do
  resource :ping
end

A few notes about the scope line:

  • specs/tests that test ‘route_to’ assertions will need to respect the fact that :api_version will be included in the list of route parameters
  • regex against paths cannot be anchored. It throws an exception at app startup time (which Passenger may hide), because those regexes are already anchored, and really you’re only working on one piece of the path at a time.
  • Order matters in routing – it is evaluated top-down so pay attention to the fallbacks.

Now, in the v2 scope, we can also override a given resource with a controller from the new namespace, since it will match first.

⇒ MP4Box Can Fix Your Online-hosted MP4s

I just discovered MP4Box (available in osx homebrew as well as other places). It has tools for rearranging your MP4 videos to optimize them for streaming. We just did this on all our videos, and not only do they start up faster on every device, it fixed some devices that refused to play our videos!

Our magic incantation was simple: MP4Box -hint $file

⇒ Log Example Names/descriptions From Rspec

This can help dig into the logs for a spec file. You can do one of these two things (both is overkill)

Local/Server Synchronization With Ruby and FSEvent

A lot of the work I do is PHP/html type coding. I try to keep a local setup that is able to run all of my code without too much trouble, but eventually all that code has to be tested on something resembling the production environment, or there are certain functions that can only be performed there (say, handling NFS mounts, or attaching to databases otherwise firewalled on my local machine). In those situations, I need to be able to quickly copy my code from my local machine to the development server. I used to do this manually, but the cycle of edit-save-copy-test was really annoying. Aptana and Eclipse have some tools that help, but I don’t use those tools anymore day-to-day, and they seemed to always get messed up.

I took while to find a suitable setup for keeping files in sync like this. Somehow I came across doubledown, a ruby script using the OSX FSEvent framework. For whatever reason, I couldn’t quite make it work on my machine (YMMV), so I took the idea and searched for other uses of FSEvent out there. I came across a few rubygems wrapping FSEvent nicely, and wrote a script around that. First, you’ll probably want to set up ssh keys. This will let you rsync over ssh without having to log in every time (kind of important on this one). I don’t like the idea of having keys that don’t have a password, so I use keychain to manage my keys. In my ~/.zshrc I have the following snippet:

The random delay lets me launch more than one shell at a time (my default windowgroup in Terminal.app is has two) without conflict.

Second, you’ll want to have a way to fully-sync your directories. The following script does this with a single command, and with some options provided by gnu getopt. The biggest features are a preset source/destination (which can be appended), and skipping .svn/.hg directories. In a rush, skipping those makes a HUGE speed difference (especially when skipping svn).

Now for the actual ruby script using FSEvent. It also includes using growl to notify on synchronization events. While not required, it is nice to know when things are synched (and it lets me know the script is still running), but it can get a bit spammy (especially running svn up on a directory).

These scripts aren’t perfect, and are meant to be modified to your own needs and preferences. Its so nice not to have to worry about manually syncing the directories anymore though!