Darwinweb

PHP Semantics in Rails--Use Blank?

May 5, 2007     

When I first started learning Rails it just made sense to me. Not that the learning curve was easy—I had to learn where everything was, and more importantly how it all worked. After 5 years of PHP development, the Rails way was obvious, but I still had to master Ruby.

A big part of Rails development philosophy is extending Ruby core classes. That is, adding utility methods to standard classes like String, Array, Hash, Fixnum, etc. Most of these are documented submodules of ActiveSupport::CoreExtensions. But there’s also a whole bunch of stuff to manage Ruby’s strong typing; methods to help in the coercion of data types. HTTP has no concept of data types, everything is passed around as text. But in any Ruby app you will typically need to deal with (at least) strings, numbers and booleans. Rails deals with this elegantly by inferring type information from the database. That works for ActiveRecord, but on the views side you need a way to deal with all these types.

Strong vs Weak Typing

PHP makes your life easy by coercing data all the time. Eventually you will need to figure out the subtleties of these coercions to deal with some special condition, but it’s pretty decent for day-to-day use. Ruby is more complicated though. The only things that evaluate to false in Ruby are nil and false. An empty string is true, 0 is true, an empty array is true. Of course there are methods to test these conditions. String, Array, and Hash all have empty?, but Fixnum and Boolean don’t. Fixnum has zero? but the others don’t. Worse yet, NilClass has none of these methods.

Even though Ruby is strongly typed in general, it also supports duck-typing which means allowing arbitrary classes to perform specific functions, and of course any method can attempt to coerce data explicitly. These two techniques allow Rails code to almost look weakly-typed. eRB templates, for instance will accept any kind of variable by calling its to_s method.

Blank? is like PHP’s == false

Now for a long time I had known about blank?, but I didn’t know it was added by Rails, and I didn’t know its specific purpose. My first assumption was that it was only for the String class. In fact it’s not documented at api.rubyonrails.org at all, and people don’t seem to talk about it much. I ended up with a lot of conditionals that looked like this:

<% if @object.value && !@object.value.empty? %>

Occasionally if I was dealing with a variable that could be of different types things would get much uglier. What I was missing was that Rails defines blank? on all classes, including NilClass to avoid precisely this type of senseless verbosity. All of these statements are true:

nil.blank?
"".blank?
" ".blank? #different and I think better than PHP
[].blank?
{}.blank?
false.blank?

The only major difference from the PHP semantics is that 0 and 0.0 are not considered blank. I guess the core team figures that 0 is often a legit value. Personally the details don’t bother me. The important thing is the blank? is defined on all the primitive classes (NilClass being the keystone). If you’re coming from PHP then you’ll right at home with blank?.