Dreams of ARel: Visualize your ActiveRecord queries

I’m currently trying to track down an ActiveRecord 3.2.* bug related to generating a count query, and thought it might be useful see a visualization of the ARel object that this query generates.

It turns out this is pretty easy!

ARel already implements a method called “to_dot” that converts your ARel into DOT, which is readable by Graphviz.

Building an API: Rails 3 vs Grape

I’ve been pretty impressed with the Grape Rack library for building an API, but I was curious how it stacks up against Rails 3, now that Rails has been Rack-ified and has steadily become more hospitable to APIs.

Using an existing Rails app with a Grape API mounted as middleware, I ran a benchmark against a vanilla API with this environment:

  • Grape 0.1.5
  • Rails 3.0.10
  • Passenger 3.0.5
  • Ruby Enterprise Edition (ruby 1.8.7), patchlevel 334
  • Macbook Pro, 2.4 GHz / 8GB, OS X 10.6.8

And it looks like Grape wins in this particular environment:

  • Grape averages 47.21 req/sec
  • Rails 3 averages 31.41  req/sec

Grape vs Rails 3 API performance

Here’s how I implemented both scenarios:

Hidden Secrets of the Rails Dev: Gotchas While Migrating from 2 to 3

Upon migrating from Rails 2 to 3, one might happen across some “gotchas”. I present a few such that you may heed caution.

ActiveSupport::Callbacks#run_callbacks

This method takes a &block parameter. In Rails 2, &block will run after each callback, and halt the chain if it returns false. In Rails 3, &block will run after the :before/:around callbacks and before the :after callbacks. More has changed about callbacks, so please read the docs.

Mail#header

ActionMailer in Rails 3 uses a different underlying library than 2: mail instead of tmail. Setting headers in the new library will accumulate headers rather than replacing them:

m['X-Something'] = 1
m['X-Something'] = 2
m.header['X-Something'] = 3

Now m has 3 values for the X-Something header: 1, 2 and 3.

ActiveRecord::Base#touch

In Rails 2, touch() ultimately calls save!() and runs through all the validation and callbacks. In Rails 3, touch() saves the record using update_all(), so no validations are performed and only the new after_touch() callback is run.

ActiveRecord#order

In Rails 2, queries are ordered like this:

User.first(:order => "name")

In Rails 3, AREL gives us a new method for queries called order(), but remember that it will accumulate order values instead of replacing them:

User.order("name").order("id").first
# ... ORDER BY name, id .... #

Remember to use reorder() to reset the value:

User.order("name").reorder("id")
# ... ORDER BY id ... #

Reorder your Authlogic persistence callbacks

One thing lacking from ActiveSupport::Callbacks, imo, is a way to reorder callbacks.

For instance, it would be nice if you could define the order in which Authlogic (which uses ActiveSupport::Callbacks) tries to persist a session (ie ‘remember’ cookie, then ‘session’ cookie, then ‘http_auth’, and so on).

Here’s some code to put at the end of your session models to prioritize their callback chains…

For Rails 2:

For Rails 3:

(link)

“SayIt ☎”, a New Pronunciation Tool!

Have you ever argued with someone over the pronunciation of a word? Let “the cloud” resolve your issue!

“SayIt ☎” is my new Kynetx/Twilio/Forvo mashup that does 1 simple thing: pronounce words

Try it… send “plasmometric” to 917.740.1911 … 

Import your data from RunnersWorld to RunKeeper!

If you need to move your information from Runner’s World into RunKeeper, but like me have run into the problem that RunKeeper doesn’t have an api (yet?) and doesn’t let you import data, then fear not!

If you like living “on the edge”, try running my script by following these steps:

  • Download the Ruby script here to any directory
  • You’ll have to run a command to get the necessary Ruby libraries: sudo gem install active_support hpricot json
  • Login to your Training Log at Runner’s World
  • Select ‘Tools’
  • Select ‘Export’ (in XML format), and click ‘Download’
  • Copy the downloaded file into the directory where you saved the Ruby script
  • Run this: ruby run_hacker.rb rwFile.xml (where ‘rwFile.xml’ is the file you downloaded from Runner’s World)
  • Finally, you’ll have to enter your RunKeeper email, RunKeeper password, and confirm every event that you would like to import.

CATCHES: 

  • For some reason the total distance in RunKeeper is recorded as “0.0” for imported Mapped runs (aka GPS runs). You can fix this by visiting RunKeeper, clicking “Edit Activity” for each Mapped run, move one of the points *very slightly* and then click “Save”. That should reset the distance correctly.
  • This should work for RunningAHEAD too, but I haven’t yet figured out how to get the maps from a RunningAHEAD account w/out logging in first.

This script has worked for me so far; let me know if you try it and encounter any problems! I’d love to abstract this into a real api wrapper, but I am on the verge of wasting too much time.

Enjoy.

(comments or bugs?)

New Name/Site for Kynetx App!!

I found some tonight to return to Similar Stories Different Take and make a few changes:

  1. renamed to Different Take (thx Cody)
  2. added support for Bloomberg News!!! 
  3. more polishing of the news-search algorithm
  4. website is now at http://different-take.com
  5. added browser extensions (courtesy of Kynetx)… the options for getting your balance of news are:
  • Bookmarklet
  • Azigo card
  • Firefox extension
  • Chrome extension
  • Internet Explorer extension

(visit the site to install)

And if you happen to be in Utah tomorrow (Apr. 27), check out the Kynetx Impact Conference!

Different Take

Kynetx App Contest: Similar News Stories

NAME: Similar News Stories

DESCRIPTION

When the user is on a major news site, this app will attempt to provide up to 20 links to similar news stories from other sources.

BACKGROUND:

This is a contest entry for the Kynetx App Contest. Go check out Kynetx if you haven’t yet— it’s a really nice platform for building context-based applications. Sort of like what hoodwink.d was for commenting, but you can do a lot more than just comments.

USE CASE

User reads a news article; User wants to see how other news sources are reporting the same story; User clicks the “Similar News Stories” bookmarklet and they’re given a list of links to matching news stories.

WORKING?

This is mostly working for me, although I have a few kinks to iron out. The current news sources it is targeted for are: CNN, NYtimes, LATimes, WSJ, DailyKos, FOXNews, Yahoo, Reuters, HuffingtonPost, and MSNBC (I’m having issues with a few of these currently).

When I have time I’d like to iron out the search algorithm, try to weed out links that point back to the same article, etc.

HOW TO INSTALL

EXAMPLE ARTICLES

Once you’ve installed, here is a sample NYTimes article, here’s one for WSJ, and here’s one for HuffingtonPost.

Sample article used with Similiar News Stories

Finally finished my PC festival mashup… and it’s at pc.muviluv.com
It has the screening dates, event dates and venue information for Sundance, Slamdance and X-DANCE (an “action sports film festival”).
There are a couple bugs I’d like to fix, but I’m also looking for some feedback for anyone who uses it ^_^

Finally finished my PC festival mashup… and it’s at pc.muviluv.com

It has the screening dates, event dates and venue information for Sundance, Slamdance and X-DANCE (an “action sports film festival”).

There are a couple bugs I’d like to fix, but I’m also looking for some feedback for anyone who uses it ^_^

Testing ye olde “querystring cache busting” trick.

When setting your site’s file cache settings, there are 2 common ways to properly save bandwidth with HTTP headers.

First method: compare the browser cache’s current versions

Set an http header such as ETag or Last-Modified that allows a client (browser) to compare its cached version of a file with the one on the server. With ETag, for example, the client checks the ETag of its cached file against the server’s version of the file, and a 304 Not Modified is sent back to the client without the actual file contents.

This method saves bandwidth, but it also requires a GET or HEAD request to the server to find out if the browser needs a new version of the file.

Second method: give the file a lifetime in the cache

To avoid the lightweight GET/HEAD request, we can also set the Expires or Cache-Control: max-age headers. Expires will tell the browser the date that the file expires (so it can make a new request to the server), and max-age will tell the browser how long the file is good for (compared to the Date header returned in the response).

Read More

Accent theme by Handsome Code


view archive



Ask me anything