Wednesday, December 15, 2010

API Design

I recently presented some opinions and ideas about web API design at Salesforce.com's Cloudstock event in San Francisco.

In the talk, I start with a poorly designed API and iterate it toward a well-behaved REST API. Along the way, I compare APIs from Facebook, LinkedIn, Twitter, Foursquare and others and share my opinions about which APIs do things well and which don't.

If you're thinking about API design, please give it a view and let me know what you think.

Here is a studio version of the talk:

Sunday, December 12, 2010

no such file to load -- spec

While trying to use Goto Alternate File (⌃⇧↓) in TextMate's Cucumber Bundle I was seeing an error like this:
no such file to load -- spec

that was pointing to line 20 of:
~/Library/Application\ Support/TextMate/Bundles/Cucumber.tmbundle/Support/lib/cucumber/mate.rb

That line reads like this:

I changed it to:

Reloaded bundles (Bundles→Bundle Editor→Reload Bundles). And now things are working fine. My guess is RSpec 2 now goes by 'rspec' instead of 'spec'.

Friday, September 24, 2010

Rails 3 Complex Join Query

I just struggled mightily to have the new Rails 3 query stuff create the SQL I wanted. I figured it out eventually. Here's the story.

I have the following models:I wanted to add a method to Person that would return all the add-ons to which a person subscribed through payment plans:So, I knew I would need this SQL query:I tried things like this, cursing the new query stuff the whole while:They all failed. Finally, I got what I wanted:It turned out to be nice and simple and I can do sweet chaining things like this:Now, I love the new Rails 3 query stuff.

Thursday, September 16, 2010

Heroku Bundler Deployment Issue

When deploying to heroku recently (bundler 1.0.0) I was getting a nasty looking error: after much struggling, I found troubleshooting directions here:
http://github.com/carlhuda/bundler/blob/master/ISSUES.md
I had to do a couple steps. first these:and then I had to edit my Gemfile to stop using any gems that pointed to github:

Tuesday, August 31, 2010

NoMethodError: undefined method 'coordinates' for #


In trying to use the latest Sunspot code (from github) for geo search with Rails 3.0.0 , I was getting the following error while running Sunspot.index!(Location.all), where Location is my ActiveRecord class for storing locations:

After searching through the new code I found that coordinates is no longer a valid field type, but instead location is to be used. location expects an object that responds to lat and lng. Sunspot provides a handly little struct called Coordinates to be this object. So, here is my model code for setting up the search:

notice the virtual attribute called coordinates which wraps the lat & lng ActiveRecord attributes. My search code now looks like this:

And my search results are coming in as expected.

Tuesday, August 10, 2010

Rails 3 doesn't like auto_link href_options

Even though the Rails doc indicates one should be able to do something like this:
auto_link(simple_format(h(text)), :href_options => { :class => 'auto-link' })
it doesn't work. looking at the Rails code in text_helper.rb, auto_link is only looking for options[:html], so :href => {} just gets ignored. one actually needs to do this:
auto_link(simple_format(h(text)), :html => {:class => 'auto-link'})
and now it works fine.

Monday, August 9, 2010

jquery auto resize fonts

I ran experiments on font-size versus line length so that I could find the proper formula to automatically resize a font in order to keep the character count per line the same as a person resizes his browser window.
UPDATE: i inverted the resize function to look traditionally linear.
Here is the jquery code that keeps the line length the same:it works pretty well with Chrome and Safari on Mac.
the initial inspiration for this code came from a post by ingeva on daniweb.

font size versus line length

I ran an experiment on Google Chrome (code below) to determine how line length varied with font size. it looked pretty linear.

Below is my guess for the curve. You can see it on Wolfram Alpha:
(line length) = 25.407 * (font size) + 6.3799

Here is the jquery/html code i used to generate the results:
the initial inspiration for fitting the curve of font size to line length came from a post by ingeva on daniweb.

Monday, August 2, 2010

NoMethodError: undefined method sanitize_for_mass_assignment

once upon a time i started getting a strange error:

NoMethodError: undefined method `sanitize_for_mass_assignment'


after poking and prodding it turned out that after running bundle install, bundler grabbed the latest version of the state_machine gem, namely 0.9.4, which makes the call to sanitize_for_mass_assignment, which wasn't found. i likely have some other dependencies missing. however, to get back to my regularly scheduled coding, i just modified my Gemfile to use a previous version of state_machine:

gem 'state_machine', '0.9.3'


now all is good and my rake tests are passing again.

Monday, July 26, 2010

iPad spell check thwarts sign-in attempts

Quick answer
In order to disable iPad's spell check the HTML form action must contain the word "login":

<form action="/login" ... >
...
</form>

Details
For some websites the iPad does not try to spell check email addresses that are a part of sign-in forms. But for many websites, it does. It's annoying.

I often have my sign-in attempt thwarted because I didn't realize my email address was 'corrected'. And when I am aware that iPad is being smart, I have to wait to type a full word and then go up to click on the 'x' to dismiss the suggested correction. And because it's hit or miss on different websites, I am always tentative when signing in, which adds to the frustration.

So, I vowed when creating my new web app that I would ensure my sign-in forms worked in a way that did not invoke the spell-checker. However, my out-of-the-box Rails 3 and Devise web app was invoking the spell checker:


Bummer. What was the difference in the HTML between the websites that invoked the spell-check and the websites that did not? Here's what I found out:

I assumed that iPad was looking at the names of the input fields to determine if it should spell check. So, I looked at sites that invoke the spell checker, like:

Ta-da List: http://123.tadalist.com/session/new
GitHub: https://github.com/login

and those that did not invoke the spell checker, like:

GMail: https://www.google.com/accounts/ServiceLogin?service=mail&ltmpl=ecobx&btmpl=mobile
Heroku: https://api.heroku.com/login

Ta-da List uses name="username" for the input text field while GitHub uses name="login". On the other hand, GMail uses name="Email" and Heroku use name="email". That must be it! It's doing a case-insensitive match for name="email".

But, no. After tweaking the HTML in my new app, it didn't work. I kept getting the spell checker in my form.

After trying many variations, I finally discovered the solution:

In order to get iPad to not invoke the spell checker on an email field while signing-in, the action on the form tag must contain the text "login". It can be capitalized or not. It can be surrounded by other text or not. But the form action must contain the characters "login".

GMail:
form action="https://www.google.com/accounts/ServiceLoginAuth"

Heroku:
form action="/login"

I am using Ruby on Rails and Devise for authentication. So for my web app, I followed the directions here:

http://wiki.github.com/plataformatec/devise/howto-change-routes-for-default-scope-to-login-logout

to change my form from using action="sign_in" to using action="login".

Now my sign-in form on the iPad behaves nicely with no spell checker:

Friday, July 23, 2010

Almost Switched to DataMapper from ActiveRecord

I was doing what seemed to be a straight-forward call with ActiveRecord from within the update method of a controller:

@project = current_person.projects.find(params[:id])


Well, when doing so I would get an error:

ActiveRecord::ReadOnlyRecord in ProjectsController#update


I was so frustrated by trying to workaround this issue that I spent the morning researching and playing with DataMapper with the intention of switching.

However, after feeling underwhelmed by the current state of DataMapper on Rails 3, I went back to finding a workaround. Luckily I found this comment at the bottom of a Pragmatic Bookshelf thread:

Hello,

An other way is to disable readonly like so:

def index
@movies = Movie.find(:all, :readonly => false, :joins => :showings, :conditions =>
["showings.starts_on < ? AND showings.ends_on > ?", Date.today, Date.today])
end


That did the trick. Why :readonly => false it not the default, I do not understand.

Tuesday, April 6, 2010

Unboxing the iPad


Unboxing the iPad
Originally uploaded by landlessness
What a beauty.