Hypsometry. Modal Synthesis.

On passwords, forgetfulness, and ease of use.

A problem.

Every site that allows password sign in has a little link on its sign in page. Sometimes it reads as a question: Forgot your password? Sometimes a first person statement: I forgot my password. Sometimes it’s just a terse fragment: Forgot password.

You click it and are taken to another page, where you can ask for a new password to be emailed to you. On the forgot-my-password page you have to enter your email address. Typically the form on that page is extremely simple: Some explanatory text, a text input field, and a submit button.

When the web application receives the submitted form, it checks its database to find the submitted email address. Assuming it finds the address, the application updates the user’s password and emails them a notice about it. If it doesn’t find the address, it returns the user to the same page and complains about the failure.

All of which is simple, straightforward, well established custom. Almost every web application has this feature, and this feature works in almost exactly the same manner across the board.

But there’s one problem here. It’s not uncommon for a user, hoping to sign in to a site, to enter his email address and then realize that he’s forgotten his password. In other words, it’s not uncommon for a user to realize that he’s only got half of the needed data after having already entered the first half.

What happens then? He finds the expected Forgot password link, clicks it, and is whisked off to the forgot-my-password page. And then has to enter his email address again.

This certainly isn’t a large problem. People type their email addresses into forms all day, every day. Lots of people use form managers to do it for them. (Though the form managers probably remember their passwords too, so they’re not in this bind in the first place.) How long does it take? A few seconds, at most. How much trouble is it? Not much.

But why cause your users any trouble at all? Even a little trouble is more than necessary.

A solution.

The solution I’m using on our new site is simple. The short explanation: The forgot-my-password link uses Javascript to grab the value of the email address already entered, then appends it, as a query parameter, to the forgot-my-password URL.

The forgot-my-password link looks like this:

<a href="/account/forgot_password" class="forgot_password">Forgot password</a>

We’ve rolled our own unobtrusive Javascript library, but it functions in many ways like Dan Webb’s Low Pro. Using that, I registered a behavior handler for the forgot-my-password link:

Event.addBehavior({
"a.forgot_password" : Account.Behavior.forgotPasswordBehavior
});

In other words, all links with a class of forgot_password get extended with the behaviors defined in Account.Behavior.forgotPasswordBehavior. That behavior is simple:

Account.Behavior = {
forgotPasswordBehavior : {
onclick: function() {
if ($F("email") != "") {
this.href = this.href + "?" + $("email").serialize();
}
}
}
}

In other words, forgotPasswordBehavior defines an onclick handler that rewrites the relevant element’s href to append whatever the user has entered in the email field. It uses Prototype to get the value of the field and rewrite it in name=value format, so that it can be passed as a URL query parameter. And it only does its work if the user has actually entered something in the email field. No point in adding the useless ?email= to the URL.

Then, in the forgot_password.rhtml view, the email field is generated like this:

<%= form.text_field(:email, :value => h(params[:email])) %>

Which creates the appropriate field using the email passed as a URL parameter as its value, if one exists.

Any user who has forgotten his password and wants to request a new one has implicitly declared his desire to use your site, and to use it now. Seems like anything you can do to help him with that is a good thing.

On nothingness, degrees of okay, bodies, success, and freaking out.

Sometimes, on Rails, you don’t want a controller method to render anything. For instance, an AJAX request might only need to know that the action succeeded. The status of the response is enough to communicate that, with no rendering required.

So you write render(:nothing => true). Rails renders nothing for you, and, by default, returns a successful status code (200 OK). Simple enough.

But how do you test for that? It’s easy to test for redirections (assert_redirected_to), successful template renderings (assert_template), and specific responses (assert_response). But testing for nothingness?

Rails renders nothingness as “ ”. Not an empty string, that is, but one space.

From a certain theoretical perspective, this is not exactly right. Nothingness in response to a GET should probably return a 204 No Content status code. After all, that is precisely the HTTP definition of “nothing to render”. And, in that case, the protocol dictates that no body be included in the response. Which seems perfect, right? Declare that you’ve got nothing to render and render nothing, communicating success implicitly. Simple and sweet.

(Things get more complicated when dealing with HEAD requests. In that case the client has explicitly asked for the headers and nothing but the headers, with no response body needed.)

However, theory tends to fall apart a bit when in the face of actual browsers. The good folks at Yahoo have looked into this while building the Yahoo User Interface Library, and have figured out that IE6, IE7, Opera, and Safari can’t handle the 204 when it comes via XMLHttpRequest. Errors result, headers are lost, responses are left undefined, and communication failure is wrongly declaimed.

(Just to complicate things further, Safari might actually have fixed this as of 3.0. I’m not clear on that, though. Either way, it’s still a cross-browser issue.)

In other words, 204 No Content will break on some of the most common browsers when used with AJAX.

What to do? Well, pass along the only appropriate status code that the browsers can handle, for starters: 200 OK. Having done that, though, you’ve now set the browsers up to expect some sort of response with their OK. And it seems that if you give Safari a completely empty response body, it freaks out a bit and doesn’t handle the response properly.

Thus the Rails hack of redefining nothingness, in this context, as a little bit of whitespace.

Knowing that, testing for the successful rendering of nothing is easy:

def assert_rendered_nothing
assert_equal(@response.body, " ", "The response was not empty.")
assert_response(:success, "The response was not successful.")
end

Check the body of the response for being “ ” and check the status code to be sure that it indicates success. Okay, and pretty good too.

An aside, though not too far: This makes my third post on nothingness this calendar year. (Cf. nihilism and the hinterlands.) I’m not sure what to say about that.

NB: The Rails definition of success is a simple one. Really, a successful status code is one that’s not in the redirection range (from 300 to 399), the client error range (from 400 to 499), or the server error range (from 500 to 599).

On the hinterlands, OpenID, cookies, jars, slippery beasts, indifference, patches of monkeys, and the difference between a general sort of nothing and nothingness in particular.

More news from the poorly mapped hinterlands of Railsia.

In our new app, we’re allowing people to sign in using OpenID. Which is cool, and progressive, and generally a Good Thing. Except for the bit that implementing it’s a nuisance.

Danny’s fully on top of the technical side, which eludes me to a surprising degree. But that’s okay, because the interface side is plenty complex enough to keep me up late. Today I’ve been working on finessing the details of the actual sign in flow, focusing on what happens when things go wrong.

We’ve got this combination sign in page with a tabbed interface, where you can sign in using either a password or an OpenID URL. Two forms, one per sign in option, although you only see one at a time.

If you try to sign in using an OpenID URL, we save that URL in a cookie called signin_openid_url. When the page is rendered, a helper method checks to see if the signin_openid_url cookie exists, and, assuming it does, renders the page such that the OpenID sign in form is visible.

Which form is displayed is determined by which form has .active applied to it. Using CSS rules like these:

#content form.content_tab
{
display: none;
}

#content form.content_tab.active
{
display: block;
}

Which form has .active applied to it is determined by the helper that checks the value of the signin_openid_url cookie. Here’s where we get to the hinterlands of Rails.

The helper we wrote initially was this:

def prefer_openid_signin?
!cookies[:signin_openid_url].nil?
end

Pretty simple: Ask for the cookie identified by :signin_openid_url, check to see if it’s nil?, and return the inverse of that answer.

And it worked most of the time. Unfortunately, it only worked most of the time.

When you enter an invalid URL and submit the form, that URL gets stuck into the cookie and all is well. When you enter no URL, however, and submit the form, things go wrong. prefer_openid_signin? was returning false, even though the signin_openid_url cookie should have been set.

Examining the parameters that were being passed, and the cookies that were being created, I could see that params[:openid_url] => "" when the empty URL form was submitted. This is as it should be. According to Rails dogma, empty text fields should yield empty strings, not nil values.

Then the signin_openid_url cookie was being created, with the correct value of "". But when I asked for the value back again, using cookies[:signin_openid_url], I got nil instead of "". Clearly, the distinction between an empty string and nil was being lost somewhere along the way.

The loss starts with CGI::Cookie, which is the Ruby Standard Library’s HTTP cookie class. CGI::Cookie always returns an Array when asked for the value of a cookie. Always. No matter that most cookies have one and only one value.

Then, in its parsing of the values sent by a client to the server, CGI::Cookie manipulates things such that any empty strings become nil. To be more precise, when a client sends a cookie with an empty string as its value to the server, CGI::Cookie turns that value into an empty Array.

ActionController.cookies uses a container to hold the cookies created by CGI::Cookie. The container’s class is CookieJar, and CookieJar behaves mostly like a Hash. But not quite. More on that in a second.

Anyway, when you ask CookieJar for the value of a cookie: CookieJar checks the size of the Array that CGI::Cookie has given it, and if it contains more than one value you get the first value. But if it contains one value, or none, you get the value of what it contains. So if it contains no values, then the Array is empty, and CookieJar returns nil.

This is contrary to what the documentation in the source says, which is that nil is returned “if no such cookie exists”. Rather, nil is returned if no such cookie exists or if such a cookie exists but contains no value.

So it seems that cookies on Rails are slippery beasts. As I said above, a CookieJar behaves mostly like a Hash. The way in which it doesn’t is that it redefines the setter and the getter methods. Which borders on perverse, in my opinion. The reason for the perversity is that it needs to handle both the setting of outgoing cookies and the getting of incoming cookies. So the interfaces for the two actions are necessarily different. However, that still doesn’t explain why they chose to combine the two different actions into one pseudo-Hash is beyond me. Why not create a new, appropriate, non-confusing interface?

Double anyway. Even though getting and setting cookies in a CookieJar doesn’t work like a Hash, you’d think it would work like a Hash in other regards. You can’t rely on it to return the values you give it, but you’d think it would be able to tell you if it has a key in it or not.

I’d think. Or I thought, so I rewrote the prefer_openid_signin? helper to just check the CookieJar for the presence of the relevant key. (Which corresponds to the existence of the relevant cookie.) As follows:

def prefer_openid_signin?
cookies.has_key?(:signin_openid_url)
end

No. No luck. Bah. Back to the source.

CookieJar, unlike every other use of Hash in Rails, is not a HashWithIndifferentAccess. Which means that if you give it a Symbol as a key when setting a value, you must use the same Symbol to get the value back. And if you use a String to set, you must use a String to get.

But that’s okay, right? Since my OpenID URL cookie creating helper looks like this:

def remember_signin_openid_url(url)
cookies[:signin_openid_url] = { :value => url, :expires => 10.years.from_now }
end

The helper sets the cookie using the Symbol:signin_openid_url, so the other helper should be able to get it using the same Symbol. Right?

Wrong. CookieJar only uses Strings as keys. If you pass it a Symbol, it converts it to the corresponding String, and never looks back. Symbols not welcome here.

Okay, got it. So I rewrote the helper as follows:

def prefer_openid_signin?
cookies.has_key?("signin_openid_url")
end

Ah. Which totally works.

But that’s annoying. I don’t want to have to remember that dealing with cookies is the one time on Rails when I need to care about whether I’m using a Symbol or a String. (And I’ve been bitten by this same, um, quirk when testing cookies.)

Thank goodness for monkey patching. I wrote the following:

module ActionController
class CookieJar < Hash
def has_key?(key)
super(key.to_s)
end
alias :contains? :has_key?
end
end

And put it in lib/cookie_jar.rb, and required it in the appropriate initializer.

Now I can check for the existence of a cookie by checking for the existence of the corresponding key, or in more elegant fashion by asking cookies.contains?(:signin_openid_url). That’s still one more hoop than I really should have to jump through, but at least it’s only one.

On hunches, Ruby, Rails, why the lucky stiff, numbers, their absence, the absence of objects, nothingness, and nihilism.

Today I was working on a view helper that creates a link to show a list. Something like the following:

def list_control(options = {})
options = do_stuff_with_the_parameters(options)
render(:partial => "link/list_control", :locals => options)
end

One option you can pass in is new_count, which is the number of new items in the list. The new_count parameter, however, is optional, since only some lists care about the newness of their items. If there’s no new_count, then the list control doesn’t talk about it at all. And new_count can, of course, be 0, and when it’s 0 the list control notes that in the title attribute but nowhere else. (So that the information is still there, and you can access it if you care, but it’s invisible most of the time.) Only if new_count exists and is greater than 0 do we display it in the link’s name.

Since Ruby lets you check to see if an object is nil?, or if it’s zero?, or if it’s empty? (Array, Hash, and String, among many others), I figured there’d be some easy way of checking to see if new_count’s either nil or 0.

Well, to save you some Pickaxe thumbing and some googling, there ain’t.

Way back in 2005, why the lucky stiff suggested that Ruby be extended to include Object#blank?. (The actual Ruby change request has vanished from the RCarchive, so why’s write-up of it seems to be the only extant discussion.) He proposed the following:

class Object
def blank?
if respond_to? :empty?
empty?
elsif respond_to? :zero?
zero?
else
!self
end
end
end

In other words, why’s Object#blank? looks to see if an object can be empty, and if so checks whether it is, in fact, empty. If the object can’t be empty but can be zero, then Object#blank? checks whether it is, in fact, zero. If the object can’t be empty or zero, then Object#blank? returns the negation of the object, which will be true if the object is nil or false, and false otherwise.

In other other words, why’s Object#blank? checks an object for all the ways in which it can be nothing, and returns true if any of them return true.

In other other other words, why’s Object#blank? is exactly what I wanted.

No wonder he said “I use this code in nearly all of my web application projects.”

So I went ahead and used count.blank?, then waited for the tests to start screaming at me. Strangely, they didn’t.

Back to Mister Google. Turns out that the clever buggers on Rails core had already added support for blank?. That’s nice, I thought; they’re a step ahead of me.

So I went ahead and wrote the code that does one thing if new_count doesn’t exist, another if it exists and is 0, and another if it exists and is not 0. And the code failed.

Back to the Rails Trac. Turns out that when the clever buggers on Rails core implemented why’s idea they left out the bit where 0 indicates blankness. empty? means blank, nil means blank, false means blank, but 0 means not blank.

Okay. That’s legitimate. Not what I need, but legitimate.

In the comments on why’s post, people thought of a lot of alternate names for blank?. I thought about it for a second, and realized that nihil? struck my fancy. Thus, Object#nihil?:

class Object
def nihil?
if respond_to?(:empty?)
empty?
elsif respond_to?(:zero?)
zero?
else
not self
end
end
end

I threw it into /lib/nihil.rb and added require 'nihil' to the app’s initializer, and that was that. Onward.

On form label generation in Rails 2.

Rails 2 has been released, as you likely know. Lots of cool new stuff has been added and documented, but there have also been many more minor changes that have gone unnoticed.

The new form helper method label is one such, a tiny little addition that’s very welcome. Now, in the context of a form_for block, you can create labels for your form elements in the same style as you’re creating the form elements themselves.

For example, instead of:

<% form_for(:user, @current_user, account_settings_url)) do |form| %>
<label for="user_email">Email</label>
<%= form.text_field(:fullname) %>
<%= submit_tag("Update email") %>
<% end %>

You can now do:

<% form_for(:user, @current_user, account_settings_url)) do |form| %>
<%= form.label(:email, "Email") %>
<%= form.text_field(:fullname) %>
<%= submit_tag("Update email") %>
<% end %>

Better still, FormHelper#label is smart enough to give you a good default for its text. So, in most common cases, you can simplify the above by leaving out the "Email" parameter:

<% form_for(:user, @current_user, account_settings_url)) do |form| %>
<%= form.label(:email) %>
<%= form.text_field(:fullname) %>
<%= submit_tag("Update email") %>
<% end %>

Whenever the text parameter is empty, FormHelper#label humanizes the name of the attribute accessing method you’ve passed it (email in this case). Which is pretty slick, in that simple Rails kind of way.

Just for the record, all of the above examples all generate the exact same HTML:

<form action="/account" method="post">
<label for="user_email">Email</label>
<input id="user_email" name="user[email]" size="30" type="text" />
<input name="commit" type="submit" value="create" />
</form>

Unfortunately, the powers that be didn’t deem it necessary to make a corresponding method that works outside of the context of form_for blocks. In a form_tag block, in other words, where there’s no model being used for reference. But it’s an easy enough method to add.

Place the following in either your own FormHelper, or open up ActionView::Helpers:FormHelper and add it directly:

def label_tag(name, value = nil, options = {})
options[:for] ||= name
value = ((value.blank? ? nil : value) || name.to_s.humanize)
content_tag(:label, value, options)
end

Enjoy.

On Rails defaults, asset timestamping, and debugging dynamically generated Javascript.

Hard to believe I’ve got to write about this again. Remember when I last talked about Rails and caching and asset timestamping? Well, here we are a year and a half later, and there’s more to say.

Working on our new project at Infoteria, we’ve got a lot of Javascript going on. We’re generating some of that dynamically (using ERB templates and some custom fanciness). And, of course, we’re using the unbeatable Firebug JS debugger.

Unfortunately, the default Rails behavior (as described in my earlier article) is to force a crude sort of asset timestamping by appending a query string to each asset’s filename. So every time we make a change to one of these dynamic Javascript files, Rails sees that a change has been made and appends a new query string. Which has the result of making it look like a new file, to the browser and to Firebug. Which, in turn, means that any breakpoints we’ve set in the last version of the file get ignored in the new version. Which makes debugging impossible.

Luckily, Rails has improved since I wrote that earlier article. You can now set RAILS_ASSET_ID to whatever you want, and if you set it to an empty string Rails will not append a query string at all.

In other words, to turn off Rails asset timestamping entirely, add the following to your environment.rb:

ENV["RAILS_ASSET_ID"] = ""

Or put it in the appropriate initializer, if you’re using Rails 2.

PS: I’ve actually got a ton more to say on this subject. The asset timestamping that Rails uses is ineffective, and their newfangled asset caching stuff is inadequate. We did a lot of work coming up with a better solution for Lingr, and we’ve done even more work on our new project. All in all, our current solution is pretty nice, allowing for dynamic CSS and JS generation, mashing up of files, caching, asset timestamping, all with a solid framework that understands quite complex combinations of page location, rendering device, and user status. More on that when I get a chance.

PPS: Apparently I used to spell geez “jeez”. Interesting.

On Haml, standards, quotation marks, and looking like everyone else.

There’s a bit of a debate going on over in the Haml Google Group. By default, Haml uses single quotation marks to wrap attribute values in the HTML it generates. Like so:

<body class='account signed_out' id='signin'>

Which is perfectly acceptable for any variety of XML, according to the W3C specifications, but is at odds with how the entire internet functions. And it looks a little funny, you know? Luckily, it’s easily changeable.

If you’d rather Haml used double quotes instead of single quotes, just drop the following in your environment.rb:

Haml::Template.options = { :attr_wrapper => %|"| }

Or put it in the appropriate initializer, if you’re using Rails 2.

Rendering a collection of things, and how it can fail.

In Rails you can iterate through a collection of stuff, rendering one partial per thing, using:

render(:partial => 'special_thing', :collection => a_bunch_of_things)

Which makes life much easier.

However, it turns out there’s this poorly documented requirement for the collection you pass in: It can’t contain hashes. You’d think – which is to say, I thought – that any enumerable would work just fine, since all Rails is doing is iterating through the collection and rendering the partial once per item.

In fact, if you take a look at the documentation for the Rails partial code, you’ll see that the examples they give clearly imply that using :collection is just shorthand for iterating through an enumerable. (Though the verbose, non-collection example uses for, which probably should be a good enough sign that something’s wrong.)

But there’s a note:

Due to backwards compatibility concerns, the collection can‘t be one of hashes. Normally you‘d also just keep domain objects, like Active Records, in there.

Why not? I’m not sure.

What happens when you try? Funny you should ask.

Say you’ve got a collection that looks like:

teams = [
{ :elephant => ryan, :soft_shelled_turtle => mary },
{ :elephant => katherine, :soft_shelled_turtle => jay }
]

And you call:

render(:partial => 'team', :collection => teams)

Rails will iterate through the collection, and for each array in teams it will assume that you want to use the value associated with the key identified by your partial’s name. (And you know what they say about assuming.) In this case, the partial is named team, so Rails will try to render _team.rhtml using teams[0][:team] and teams[1][:team]. And, since the default value of a hash is nil, your partial get passed a series of nils and will probably fail to render. Not exactly what you might hope.

On another hand, if you’re using the same collection but instead call:

render(:partial => 'elephant', :collection => teams)

you might have better luck, since Rails will pass teams[0][:elephant] and teams[1][:elephant] to your partial, and at least those aren’t nil. Though are they what you want? Probably not.

Okay, now that I’ve explained the problem, here’s the good news: This will not be a problem in Rails 2. Ticket #8958 removed the deprecated cruft from ActionView, and, in so doing, freed us up to use collections of hashes in our partial rendering.

Aren’t you excited? Thought so.